42 #include <QTextStream> 50 #include <ogr_srs_api.h> 51 #include <cpl_error.h> 53 #include <cpl_string.h> 59 static OGRDataSourceH myOGROpen(
const char *pszName,
int bUpdate, OGRSFDriverH *phDriver )
61 OGRSFDriverH hDriver =
nullptr;
62 OGRDataSourceH hDS = OGROpen( pszName, bUpdate, &hDriver );
65 QString drvName = OGR_Dr_GetName( hDriver );
66 if ( drvName ==
"BNA" )
68 OGR_DS_Destroy( hDS );
95 const QString &vectorFileName,
96 const QString &fileEncoding,
100 const QString &driverName,
101 const QStringList &datasourceOptions,
102 const QStringList &layerOptions,
103 QString *newFilename,
105 QgsFeatureSink::SinkFlags sinkFlags,
113 init( vectorFileName, fileEncoding, fields, geometryType,
114 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
119 const QString &fileEncoding,
123 const QString &driverName,
124 const QStringList &datasourceOptions,
125 const QStringList &layerOptions,
126 QString *newFilename,
129 const QString &layerName,
137 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
138 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
139 layerName, action, newLayer,
nullptr );
144 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
148 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 149 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
154 if ( !driverMetadata )
157 return CSLFetchBoolean( driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
159 return driverName == QLatin1String(
"DXF" ) || driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"MapInfo File" );
163 void QgsVectorFileWriter::init( QString vectorFileName,
164 QString fileEncoding,
168 const QString &driverName,
169 QStringList datasourceOptions,
170 QStringList layerOptions,
171 QString *newFilename,
173 const QString &layerNameIn,
175 QString *newLayer, SinkFlags sinkFlags )
179 if ( vectorFileName.isEmpty() )
186 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
190 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
193 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
195 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
198 else if ( driverName == QLatin1String(
"DBF file" ) )
201 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
203 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
213 OGRSFDriverH poDriver;
216 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
220 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
222 QString::fromUtf8( CPLGetLastErrorMsg() ) );
232 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
237 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
239 vectorFileName += QLatin1String(
".shp" );
241 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
243 vectorFileName += QLatin1String(
".dbf" );
253 QStringList allExts = metadata.
ext.split(
' ', QString::SkipEmptyParts );
255 Q_FOREACH (
const QString &ext, allExts )
257 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
266 vectorFileName +=
'.' + allExts[0];
272 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
274 QDir dir( vectorFileName );
277 QFileInfoList fileList = dir.entryInfoList(
278 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
279 Q_FOREACH (
const QFileInfo &info, fileList )
281 QFile::remove( info.absoluteFilePath() );
284 QDir().rmdir( vectorFileName );
288 QFile::remove( vectorFileName );
303 char **options =
nullptr;
304 if ( !datasourceOptions.isEmpty() )
306 options =
new char *[ datasourceOptions.size() + 1 ];
307 for (
int i = 0; i < datasourceOptions.size(); i++ )
309 QgsDebugMsg( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ) );
310 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
312 options[ datasourceOptions.size()] =
nullptr;
318 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
320 mDS.reset( myOGROpen( vectorFileName.toUtf8().constData(), TRUE, nullptr ) );
324 for (
int i = 0; i < datasourceOptions.size(); i++ )
325 CPLFree( options[i] );
334 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
335 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
337 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
338 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
342 QString layerName( layerNameIn );
343 if ( layerName.isEmpty() )
344 layerName = QFileInfo( vectorFileName ).baseName();
348 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
349 for (
int i = 0; i < layer_count; i++ )
351 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
352 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
354 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
357 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
358 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
368 QgsDebugMsg( QStringLiteral(
"Created data source" ) );
372 QgsDebugMsg( QStringLiteral(
"Opened data source in update mode" ) );
376 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
379 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
382 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
383 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
386 QgsDebugMsg(
"error finding QTextCodec for " + enc );
387 mCodec = QTextCodec::codecForLocale();
395 QString srsWkt = srs.
toWkt();
397 mOgrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().constData() );
398 #if GDAL_VERSION_MAJOR >= 3 401 OSRSetAxisMappingStrategy(
mOgrRef, OAMS_TRADITIONAL_GIS_ORDER );
410 int optIndex = layerOptions.indexOf( QStringLiteral(
"FEATURE_DATASET=" ) );
411 if ( optIndex != -1 )
413 layerOptions.removeAt( optIndex );
416 if ( !layerOptions.isEmpty() )
418 options =
new char *[ layerOptions.size() + 1 ];
419 for (
int i = 0; i < layerOptions.size(); i++ )
421 QgsDebugMsg( QStringLiteral(
"-lco=%1" ).arg( layerOptions[i] ) );
422 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
424 options[ layerOptions.size()] =
nullptr;
428 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
432 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
435 *newLayer = OGR_L_GetName(
mLayer );
436 if ( driverName == QLatin1String(
"GPX" ) )
443 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
444 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
446 *newLayer = QStringLiteral(
"waypoints" );
453 const char *pszForceGPXTrack
454 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
455 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
456 *newLayer = QStringLiteral(
"tracks" );
458 *newLayer = QStringLiteral(
"routes" );
465 const char *pszForceGPXRoute
466 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
467 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
468 *newLayer = QStringLiteral(
"routes" );
470 *newLayer = QStringLiteral(
"tracks" );
480 else if ( driverName == QLatin1String(
"DGN" ) )
482 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
486 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
491 for (
int i = 0; i < layerOptions.size(); i++ )
492 CPLFree( options[i] );
498 if ( !settings.
value( QStringLiteral(
"qgis/ignoreShapeEncoding" ),
true ).toBool() )
500 CPLSetConfigOption(
"SHAPE_ENCODING",
nullptr );
507 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
508 QFile prjFile( layerName +
".qpj" );
509 if ( prjFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
511 QTextStream prjStream( &prjFile );
512 prjStream << srs.
toWkt().toLocal8Bit().constData() << endl;
517 QgsDebugMsg(
"Couldn't open file " + layerName +
".qpj" );
525 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
526 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
528 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
529 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
534 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
539 QgsDebugMsg(
"creating " + QString::number( fields.
size() ) +
" fields" );
543 QSet<int> existingIdxs;
550 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;
641 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
642 .arg( attrField.
name() );
647 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
650 for ( i = 0; i < 10; i++ )
652 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
655 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
658 if ( j == fields.
size() )
664 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
669 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
676 OGR_Fld_SetWidth( fld.get(), ogrWidth );
679 if ( ogrPrecision >= 0 )
681 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
684 switch ( attrField.
type() )
687 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
695 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
696 " width " + QString::number( ogrWidth ) +
697 " precision " + QString::number( ogrPrecision ) );
698 if ( OGR_L_CreateField(
mLayer, fld.get(), true ) != OGRERR_NONE )
701 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
702 .arg( attrField.
name(),
703 QString::fromUtf8( CPLGetLastErrorMsg() ) );
708 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
709 QgsDebugMsg( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ) );
710 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
713 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
718 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
719 .arg( attrField.
name(),
720 QString::fromUtf8( CPLGetLastErrorMsg() ) );
726 existingIdxs.insert( ogrIdx );
732 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
735 QString name( attrField.
name() );
736 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
746 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
752 QgsDebugMsg( QStringLiteral(
"Done creating fields" ) );
757 *newFilename = vectorFileName;
760 mUsingTransaction =
true;
761 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
763 mUsingTransaction =
false;
773 class QgsVectorFileWriterMetadataContainer
777 QgsVectorFileWriterMetadataContainer()
779 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
780 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
783 datasetOptions.clear();
784 layerOptions.clear();
788 QStringLiteral(
"Arc/Info ASCII Coverage" ),
789 QObject::tr(
"Arc/Info ASCII Coverage" ),
790 QStringLiteral(
"*.e00" ),
791 QStringLiteral(
"e00" ),
798 datasetOptions.clear();
799 layerOptions.clear();
802 QObject::tr(
"New BNA files are created by the " 803 "systems default line termination conventions. " 804 "This may be overridden here." ),
806 << QStringLiteral(
"CRLF" )
807 << QStringLiteral(
"LF" ),
813 QObject::tr(
"By default, BNA files are created in multi-line format. " 814 "For each record, the first line contains the identifiers and the " 815 "type/number of coordinates to follow. Each following line contains " 816 "a pair of coordinates." ),
821 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. " 822 "Some software packages only support a precise number of identifiers. " 823 "You can override the default value (2) by a precise value." ),
825 << QStringLiteral(
"2" )
826 << QStringLiteral(
"3" )
827 << QStringLiteral(
"4" )
828 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
829 QStringLiteral(
"2" )
833 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. " 834 "This will only work if the feature has previously been read from a BNA file. " 835 "As some software packages do not support ellipses/circles in BNA data file, " 836 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not " 837 "to export them as such, but keep them as polygons." ),
842 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
847 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
853 QStringLiteral(
"Atlas BNA" ),
854 QObject::tr(
"Atlas BNA" ),
855 QStringLiteral(
"*.bna" ),
856 QStringLiteral(
"bna" ),
863 datasetOptions.clear();
864 layerOptions.clear();
867 QObject::tr(
"By default when creating new .csv files they " 868 "are created with the line termination conventions " 869 "of the local platform (CR/LF on Win32 or LF on all other systems). " 870 "This may be overridden through the use of the LINEFORMAT option." ),
872 << QStringLiteral(
"CRLF" )
873 << QStringLiteral(
"LF" ),
879 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. " 880 "It is possible to export the geometry in its WKT representation by " 881 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries " 882 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY " 883 "or GEOMETRY=AS_YX." ),
885 << QStringLiteral(
"AS_WKT" )
886 << QStringLiteral(
"AS_XYZ" )
887 << QStringLiteral(
"AS_XY" )
888 << QStringLiteral(
"AS_YX" ),
894 QObject::tr(
"Create the associated .csvt file to describe the type of each " 895 "column of the layer and its optional width and precision." ),
900 QObject::tr(
"Field separator character." ),
902 << QStringLiteral(
"COMMA" )
903 << QStringLiteral(
"SEMICOLON" )
904 << QStringLiteral(
"TAB" ),
905 QStringLiteral(
"COMMA" )
908 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 910 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
912 << QStringLiteral(
"IF_NEEDED" )
913 << QStringLiteral(
"IF_AMBIGUOUS" )
914 << QStringLiteral(
"ALWAYS" ),
915 QStringLiteral(
"IF_AMBIGUOUS" )
920 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
926 QStringLiteral(
"Comma Separated Value [CSV]" ),
927 QObject::tr(
"Comma Separated Value [CSV]" ),
928 QStringLiteral(
"*.csv" ),
929 QStringLiteral(
"csv" ),
936 datasetOptions.clear();
937 layerOptions.clear();
940 QObject::tr(
"Override the type of shapefile created. " 941 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, " 942 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or " 943 "MULTIPOINTZ for 3D;" ) +
944 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries" 945 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured" 947 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
948 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
952 << QStringLiteral(
"NULL" )
953 << QStringLiteral(
"POINT" )
954 << QStringLiteral(
"ARC" )
955 << QStringLiteral(
"POLYGON" )
956 << QStringLiteral(
"MULTIPOINT" )
957 << QStringLiteral(
"POINTZ" )
958 << QStringLiteral(
"ARCZ" )
959 << QStringLiteral(
"POLYGONZ" )
960 << QStringLiteral(
"MULTIPOINTZ" )
961 << QStringLiteral(
"POINTM" )
962 << QStringLiteral(
"ARCM" )
963 << QStringLiteral(
"POLYGONM" )
964 << QStringLiteral(
"MULTIPOINTM" )
965 << QStringLiteral(
"POINTZM" )
966 << QStringLiteral(
"ARCZM" )
967 << QStringLiteral(
"POLYGONZM" )
968 << QStringLiteral(
"MULTIPOINTZM" )
969 #
if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0)
970 << QStringLiteral(
"MULTIPATCH" )
981 QObject::tr(
"Set the encoding value in the DBF file. " 982 "The default value is LDID/87. It is not clear " 983 "what other values may be appropriate." ),
991 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
997 QStringLiteral(
"ESRI Shapefile" ),
998 QObject::tr(
"ESRI Shapefile" ),
999 QStringLiteral(
"*.shp" ),
1000 QStringLiteral(
"shp" ),
1007 datasetOptions.clear();
1008 layerOptions.clear();
1012 QStringLiteral(
"DBF File" ),
1013 QObject::tr(
"DBF File" ),
1014 QStringLiteral(
"*.dbf" ),
1015 QStringLiteral(
"dbf" ),
1022 datasetOptions.clear();
1023 layerOptions.clear();
1027 QStringLiteral(
"FMEObjects Gateway" ),
1028 QObject::tr(
"FMEObjects Gateway" ),
1029 QStringLiteral(
"*.fdd" ),
1030 QStringLiteral(
"fdd" ),
1037 datasetOptions.clear();
1038 layerOptions.clear();
1041 QObject::tr(
"Set to YES to write a bbox property with the bounding box " 1042 "of the geometries at the feature and feature collection level." ),
1047 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. " 1048 "Default to 15. Truncation will occur to remove trailing zeros." ),
1054 QStringLiteral(
"GeoJSON" ),
1055 QObject::tr(
"GeoJSON" ),
1056 QStringLiteral(
"*.geojson" ),
1057 QStringLiteral(
"geojson" ),
1060 QStringLiteral(
"UTF-8" )
1065 datasetOptions.clear();
1066 layerOptions.clear();
1069 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. " 1070 "Default value : RSS" ),
1072 << QStringLiteral(
"RSS" )
1073 << QStringLiteral(
"ATOM" ),
1074 QStringLiteral(
"RSS" )
1078 QObject::tr(
"The encoding of location information. Default value : SIMPLE. " 1079 "W3C_GEO only supports point geometries. " 1080 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1082 << QStringLiteral(
"SIMPLE" )
1083 << QStringLiteral(
"GML" )
1084 << QStringLiteral(
"W3C_GEO" ),
1085 QStringLiteral(
"SIMPLE" )
1089 QObject::tr(
"If defined to YES, extension fields will be written. " 1090 "If the field name not found in the base schema matches " 1091 "the foo_bar pattern, foo will be considered as the namespace " 1092 "of the element, and a <foo:bar> element will be written. " 1093 "Otherwise, elements will be written in the <ogr:> namespace." ),
1098 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. " 1099 "The user will have to provide the appropriate header and footer of the document." ),
1104 QObject::tr(
"XML content that will be put between the <channel> element and the " 1105 "first <item> element for a RSS document, or between the xml tag and " 1106 "the first <entry> element for an Atom document." ),
1111 QObject::tr(
"Value put inside the <title> element in the header. " 1112 "If not provided, a dummy value will be used as that element is compulsory." ),
1117 QObject::tr(
"Value put inside the <description> element in the header. " 1118 "If not provided, a dummy value will be used as that element is compulsory." ),
1123 QObject::tr(
"Value put inside the <link> element in the header. " 1124 "If not provided, a dummy value will be used as that element is compulsory." ),
1129 QObject::tr(
"Value put inside the <updated> element in the header. " 1130 "Should be formatted as a XML datetime. " 1131 "If not provided, a dummy value will be used as that element is compulsory." ),
1136 QObject::tr(
"Value put inside the <author><name> element in the header. " 1137 "If not provided, a dummy value will be used as that element is compulsory." ),
1142 QObject::tr(
"Value put inside the <id> element in the header. " 1143 "If not provided, a dummy value will be used as that element is compulsory." ),
1149 QStringLiteral(
"GeoRSS" ),
1150 QObject::tr(
"GeoRSS" ),
1151 QStringLiteral(
"*.xml" ),
1152 QStringLiteral(
"xml" ),
1155 QStringLiteral(
"UTF-8" )
1160 datasetOptions.clear();
1161 layerOptions.clear();
1164 QObject::tr(
"If provided, this URI will be inserted as the schema location. " 1165 "Note that the schema file isn't actually accessed by OGR, so it " 1166 "is up to the user to ensure it will match the schema of the OGR " 1167 "produced GML data file." ),
1172 QObject::tr(
"This writes a GML application schema file to a corresponding " 1173 ".xsd file (with the same basename). If INTERNAL is used the " 1174 "schema is written within the GML file, but this is experimental " 1175 "and almost certainly not valid XML. " 1176 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1178 << QStringLiteral(
"EXTERNAL" )
1179 << QStringLiteral(
"INTERNAL" )
1180 << QStringLiteral(
"OFF" ),
1181 QStringLiteral(
"EXTERNAL" )
1185 QObject::tr(
"This is the prefix for the application target namespace." ),
1186 QStringLiteral(
"ogr" )
1190 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the " 1191 "application target namespace in the GML file." ),
1196 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. " 1197 "This is the application target namespace." ),
1198 QStringLiteral(
"http://ogr.maptools.org/" )
1202 QObject::tr(
"If not specified, GML2 will be used." ),
1204 << QStringLiteral(
"GML3" )
1205 << QStringLiteral(
"GML3Deegree" )
1206 << QStringLiteral(
"GML3.2" ),
1212 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. " 1213 "If YES, SRS with EPSG authority will be written with the " 1214 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a " 1215 "geographic SRS without explicit AXIS order, but that the same " 1216 "SRS authority code imported with ImportFromEPSGA() should be " 1217 "treated as lat/long, then the function will take care of coordinate " 1218 "order swapping. If set to NO, SRS with EPSG authority will be " 1219 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1224 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. " 1225 "If set to NO, the <gml:boundedBy> element will not be written for " 1231 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces " 1232 "for more readability, but at the expense of file size." ),
1239 QStringLiteral(
"Geography Markup Language [GML]" ),
1240 QObject::tr(
"Geography Markup Language [GML]" ),
1241 QStringLiteral(
"*.gml" ),
1242 QStringLiteral(
"gml" ),
1245 QStringLiteral(
"UTF-8" )
1250 datasetOptions.clear();
1251 layerOptions.clear();
1254 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1259 QObject::tr(
"Human-readable description for the layer content" ),
1264 QObject::tr(
"Name for the feature identifier column" ),
1265 QStringLiteral(
"fid" )
1269 QObject::tr(
"Name for the geometry column" ),
1270 QStringLiteral(
"geom" )
1274 QObject::tr(
"If a spatial index must be created." ),
1280 QStringLiteral(
"GeoPackage" ),
1281 QObject::tr(
"GeoPackage" ),
1282 QStringLiteral(
"*.gpkg" ),
1283 QStringLiteral(
"gpkg" ),
1286 QStringLiteral(
"UTF-8" )
1291 datasetOptions.clear();
1292 layerOptions.clear();
1296 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1297 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1298 QStringLiteral(
"*.gmt" ),
1299 QStringLiteral(
"gmt" ),
1306 datasetOptions.clear();
1307 layerOptions.clear();
1310 QObject::tr(
"By default when writing a layer whose features are of " 1311 "type wkbLineString, the GPX driver chooses to write " 1312 "them as routes. If FORCE_GPX_TRACK=YES is specified, " 1313 "they will be written as tracks." ),
1318 QObject::tr(
"By default when writing a layer whose features are of " 1319 "type wkbMultiLineString, the GPX driver chooses to write " 1320 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, " 1321 "they will be written as routes, provided that the multilines " 1322 "are composed of only one single line." ),
1327 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, " 1328 "extra fields will be written inside the <extensions> tag." ),
1333 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL " 1334 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1335 QStringLiteral(
"ogr" )
1339 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS " 1340 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1341 QStringLiteral(
"http://osgeo.org/gdal" )
1345 QObject::tr(
"By default files are created with the line termination " 1346 "conventions of the local platform (CR/LF on win32 or LF " 1347 "on all other systems). This may be overridden through use " 1348 "of the LINEFORMAT layer creation option which may have a value " 1349 "of CRLF (DOS format) or LF (Unix format)." ),
1351 << QStringLiteral(
"CRLF" )
1352 << QStringLiteral(
"LF" ),
1359 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1360 QObject::tr(
"GPS eXchange Format [GPX]" ),
1361 QStringLiteral(
"*.gpx" ),
1362 QStringLiteral(
"gpx" ),
1365 QStringLiteral(
"UTF-8" )
1370 datasetOptions.clear();
1371 layerOptions.clear();
1375 QStringLiteral(
"INTERLIS 1" ),
1376 QObject::tr(
"INTERLIS 1" ),
1377 QStringLiteral(
"*.itf *.xml *.ili" ),
1378 QStringLiteral(
"ili" ),
1385 datasetOptions.clear();
1386 layerOptions.clear();
1390 QStringLiteral(
"INTERLIS 2" ),
1391 QObject::tr(
"INTERLIS 2" ),
1392 QStringLiteral(
"*.xtf *.xml *.ili" ),
1393 QStringLiteral(
"ili" ),
1400 datasetOptions.clear();
1401 layerOptions.clear();
1404 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1405 QStringLiteral(
"Name" )
1409 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1410 QStringLiteral(
"Description" )
1414 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. " 1415 "This will only affect 3D geometries and must be one of the valid KML options." ),
1417 << QStringLiteral(
"clampToGround" )
1418 << QStringLiteral(
"relativeToGround" )
1419 << QStringLiteral(
"absolute" ),
1420 QStringLiteral(
"relativeToGround" )
1423 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,2,0) 1425 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified " 1426 "the id of the root <Document> node. The default value is root_doc." ),
1427 QStringLiteral(
"root_doc" )
1433 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1434 QObject::tr(
"Keyhole Markup Language [KML]" ),
1435 QStringLiteral(
"*.kml" ),
1436 QStringLiteral(
"kml" ),
1439 QStringLiteral(
"UTF-8" )
1444 datasetOptions.clear();
1445 layerOptions.clear();
1447 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1450 QObject::tr(
"Use this to turn on 'quick spatial index mode'. " 1451 "In this mode writing files can be about 5 times faster, " 1452 "but spatial queries can be up to 30 times slower." ),
1454 << QStringLiteral(
"QUICK" )
1455 << QStringLiteral(
"OPTIMIZED" ),
1456 QStringLiteral(
"QUICK" ),
1461 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults " 1462 "to 512. MapInfo 15.2 and above creates .tab files with a " 1463 "blocksize of 16384 bytes. Any MapInfo version should be " 1464 "able to handle block sizes from 512 to 32256." ),
1468 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the " 1469 "accuracy of the coordinates. Note: the geometry of written " 1470 "features must be within the defined box." ),
1474 insertMapInfoOptions( datasetOptions, layerOptions );
1478 QStringLiteral(
"Mapinfo" ),
1479 QObject::tr(
"Mapinfo TAB" ),
1480 QStringLiteral(
"*.tab" ),
1481 QStringLiteral(
"tab" ),
1486 datasetOptions.clear();
1487 layerOptions.clear();
1488 insertMapInfoOptions( datasetOptions, layerOptions );
1493 QStringLiteral(
"Mapinfo" ),
1494 QObject::tr(
"Mapinfo MIF" ),
1495 QStringLiteral(
"*.mif" ),
1496 QStringLiteral(
"mif" ),
1503 datasetOptions.clear();
1504 layerOptions.clear();
1507 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) " 1508 "seed file should be used. This option is ignored if the SEED option is provided." ),
1513 QObject::tr(
"Override the seed file to use." ),
1518 QObject::tr(
"Indicate whether the whole seed file should be copied. " 1519 "If not, only the first three elements will be copied." ),
1524 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1529 QObject::tr(
"Override the master unit name from the seed file with " 1530 "the provided one or two character unit name." ),
1535 QObject::tr(
"Override the sub unit name from the seed file with the provided " 1536 "one or two character unit name." ),
1541 QObject::tr(
"Override the number of subunits per master unit. " 1542 "By default the seed file value is used." ),
1547 QObject::tr(
"Override the number of UORs (Units of Resolution) " 1548 "per sub unit. By default the seed file value is used." ),
1553 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. " 1554 "By default the origin from the seed file is used." ),
1560 QStringLiteral(
"Microstation DGN" ),
1561 QObject::tr(
"Microstation DGN" ),
1562 QStringLiteral(
"*.dgn" ),
1563 QStringLiteral(
"dgn" ),
1570 datasetOptions.clear();
1571 layerOptions.clear();
1574 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1576 << QStringLiteral(
"APPLY" )
1577 << QStringLiteral(
"IGNORE" ),
1578 QStringLiteral(
"APPLY" )
1582 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. " 1583 "Multipoint geometries are not well handled by many formats, " 1584 "so it can be convenient to split single sounding features with many points " 1585 "into many single point features." ),
1590 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth " 1591 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is " 1597 QObject::tr(
"Should all the low level geometry primitives be returned as special " 1598 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1603 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will " 1604 "be preserved as a special numeric value. This option should not generally " 1605 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1610 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing " 1611 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1616 QObject::tr(
"Should additional attributes relating features to their underlying " 1617 "geometric primitives be attached. These are the values of the FSPT group, " 1618 "and are primarily needed when doing S-57 to S-57 translations." ),
1623 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding " 1624 "specified in the S57 DSSI record." ),
1632 QStringLiteral(
"S-57 Base file" ),
1633 QObject::tr(
"S-57 Base file" ),
1634 QStringLiteral(
"*.000" ),
1635 QStringLiteral(
"000" ),
1642 datasetOptions.clear();
1643 layerOptions.clear();
1647 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1648 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1649 QStringLiteral(
"*catd.ddf" ),
1650 QStringLiteral(
"ddf" ),
1657 datasetOptions.clear();
1658 layerOptions.clear();
1661 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1662 "tables in a new database. By default these metadata tables are created " 1663 "when a new database is created." ),
1669 QStringLiteral(
"NO" )
1674 QStringLiteral(
"NO" )
1678 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. " 1679 "This is generally more space and processing efficient, but harder " 1680 "to inspect or use in simple applications than WKT (Well Known Text)." ),
1682 << QStringLiteral(
"WKB" )
1683 << QStringLiteral(
"WKT" ),
1684 QStringLiteral(
"WKB" )
1688 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1689 "in SQLite. Laundered names will be converted to lower case and some special " 1690 "characters(' - #) will be changed to underscores." ),
1695 QStringLiteral(
"NO" )
1699 QStringLiteral(
"NO" )
1707 QObject::tr(
"column_name1[,column_name2, ...] A list of (String) columns that " 1708 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1709 "for databases that have big string blobs. However, use with care, since " 1710 "the value of such columns will be seen as compressed binary content with " 1711 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1712 "modifying or querying compressed columns, compression/decompression is " 1713 "done transparently. However, such columns cannot be (easily) queried with " 1714 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1715 "have the 'VARCHAR_deflate' declaration type." ),
1721 QStringLiteral(
"SQLite" ),
1722 QObject::tr(
"SQLite" ),
1723 QStringLiteral(
"*.sqlite" ),
1724 QStringLiteral(
"sqlite" ),
1727 QStringLiteral(
"UTF-8" )
1732 datasetOptions.clear();
1733 layerOptions.clear();
1736 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 1737 "tables in a new database. By default these metadata tables are created " 1738 "when a new database is created." ),
1743 QStringLiteral(
"YES" )
1747 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. " 1748 "Set to NO for regular SQLite databases." ),
1753 QStringLiteral(
"SPATIALITE" )
1757 QObject::tr(
"Controls whether layer and field names will be laundered for easier use " 1758 "in SQLite. Laundered names will be converted to lower case and some special " 1759 "characters(' - #) will be changed to underscores." ),
1764 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked " 1765 "against libspatialite, this option can be used to control if a spatial " 1766 "index must be created." ),
1771 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, " 1772 "this option can be used to control if the compressed format for " 1773 "geometries (LINESTRINGs, POLYGONs) must be used." ),
1778 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. " 1779 "When this option isn't specified and that a SRS is associated with the " 1780 "layer, a search is made in the spatial_ref_sys to find a match for the " 1781 "SRS, and, if there is no match, a new entry is inserted for the SRS in " 1782 "the spatial_ref_sys table. When the SRID option is specified, this " 1783 "search (and the eventual insertion of a new entry) will not be done: " 1784 "the specified SRID is used as such." ),
1789 QObject::tr(
"column_name1[,column_name2, ...] A list of (String) columns that " 1790 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 1791 "for databases that have big string blobs. However, use with care, since " 1792 "the value of such columns will be seen as compressed binary content with " 1793 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 1794 "modifying or queryings compressed columns, compression/decompression is " 1795 "done transparently. However, such columns cannot be (easily) queried with " 1796 "an attribute filter or WHERE clause. Note: in table definition, such columns " 1797 "have the 'VARCHAR_deflate' declaration type." ),
1803 QStringLiteral(
"SpatiaLite" ),
1804 QObject::tr(
"SpatiaLite" ),
1805 QStringLiteral(
"*.sqlite" ),
1806 QStringLiteral(
"sqlite" ),
1809 QStringLiteral(
"UTF-8" )
1813 datasetOptions.clear();
1814 layerOptions.clear();
1817 QObject::tr(
"Override the header file used - in place of header.dxf." ),
1822 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
1828 QStringLiteral(
"AutoCAD DXF" ),
1829 QObject::tr(
"AutoCAD DXF" ),
1830 QStringLiteral(
"*.dxf" ),
1831 QStringLiteral(
"dxf" ),
1838 datasetOptions.clear();
1839 layerOptions.clear();
1842 QObject::tr(
"Indicates the GeoConcept export file extension. " 1843 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1845 << QStringLiteral(
"GXT" )
1846 << QStringLiteral(
"TXT" ),
1847 QStringLiteral(
"GXT" )
1851 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: " 1852 "In this file, every line must start with //# followed by a keyword. " 1853 "Lines starting with // are comments." ),
1858 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name " 1859 "found in the GCT file for a type section. The SUBTYPE corresponds to one of " 1860 "the Name found in the GCT file for a sub-type section within the previous " 1867 QStringLiteral(
"Geoconcept" ),
1868 QObject::tr(
"Geoconcept" ),
1869 QStringLiteral(
"*.gxt *.txt" ),
1870 QStringLiteral(
"gxt" ),
1877 datasetOptions.clear();
1878 layerOptions.clear();
1881 QObject::tr(
"When this option is set, the new layer will be created inside the named " 1882 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
1887 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
1888 QStringLiteral(
"SHAPE" )
1892 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
1893 QStringLiteral(
"OBJECTID" )
1898 QStringLiteral(
"ESRI FileGDB" ),
1899 QObject::tr(
"ESRI FileGDB" ),
1900 QStringLiteral(
"*.gdb" ),
1901 QStringLiteral(
"gdb" ),
1904 QStringLiteral(
"UTF-8" )
1909 datasetOptions.clear();
1910 layerOptions.clear();
1913 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 1914 "to STRING, all fields will be of String type." ),
1916 << QStringLiteral(
"AUTO" )
1917 << QStringLiteral(
"STRING" ),
1918 QStringLiteral(
"AUTO" ),
1923 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 1924 "if the first line might be the name of columns. If set to FORCE, the driver " 1925 "will consider the first line as the header line. If set to " 1926 "DISABLE, it will be considered as the first feature. Otherwise " 1927 "auto-detection will occur." ),
1929 << QStringLiteral(
"FORCE" )
1930 << QStringLiteral(
"DISABLE" )
1931 << QStringLiteral(
"AUTO" ),
1932 QStringLiteral(
"AUTO" ),
1938 QStringLiteral(
"MS Office Open XML spreadsheet" ),
1939 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
1940 QStringLiteral(
"*.xlsx" ),
1941 QStringLiteral(
"xlsx" ),
1944 QStringLiteral(
"UTF-8" )
1949 datasetOptions.clear();
1950 layerOptions.clear();
1953 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set " 1954 "to STRING, all fields will be of String type." ),
1956 << QStringLiteral(
"AUTO" )
1957 << QStringLiteral(
"STRING" ),
1958 QStringLiteral(
"AUTO" ),
1963 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect " 1964 "if the first line might be the name of columns. If set to FORCE, the driver " 1965 "will consider the first line as the header line. If set to " 1966 "DISABLE, it will be considered as the first feature. Otherwise " 1967 "auto-detection will occur." ),
1969 << QStringLiteral(
"FORCE" )
1970 << QStringLiteral(
"DISABLE" )
1971 << QStringLiteral(
"AUTO" ),
1972 QStringLiteral(
"AUTO" ),
1978 QStringLiteral(
"Open Document Spreadsheet" ),
1979 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
1980 QStringLiteral(
"*.ods" ),
1981 QStringLiteral(
"ods" ),
1984 QStringLiteral(
"UTF-8" )
1989 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
1990 QgsVectorFileWriterMetadataContainer &
operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
1991 ~QgsVectorFileWriterMetadataContainer()
1995 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
1996 delete optionIt.value();
1997 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
1998 delete optionIt.value();
2009 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2010 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2012 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2014 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2016 driverMetadata = it.value();
2029 return QStringList();
2038 return QStringList();
2045 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2071 QgsFeatureList::iterator fIt = features.begin();
2073 for ( ; fIt != features.end(); ++fIt )
2090 mRenderContext.expressionContext().setFeature( feature );
2093 QString styleString;
2094 QString currentStyle;
2096 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2097 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2099 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2100 for (
int i = 0; i < nSymbolLayers; ++i )
2103 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2109 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2110 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2112 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2116 if ( symbolIt != symbols.constBegin() || i != 0 )
2118 styleString.append(
';' );
2120 styleString.append( currentStyle );
2124 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2125 if ( !writeFeature(
mLayer, poFeature.get() ) )
2132 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2137 if ( !writeFeature(
mLayer, poFeature.get() ) )
2154 if ( fid > std::numeric_limits<int>::max() )
2156 QgsDebugMsg( QStringLiteral(
"feature id %1 too large." ).arg( fid ) );
2157 OGRErr err = OGR_F_SetFID( poFeature.get(),
static_cast<long>( fid ) );
2158 if ( err != OGRERR_NONE )
2160 QgsDebugMsg( QStringLiteral(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
2161 .arg( feature.
id() )
2162 .arg( err ).arg( CPLGetLastErrorMsg() )
2170 int fldIdx = it.key();
2171 int ogrField = it.value();
2173 QVariant attrValue = feature.
attribute( fldIdx );
2176 if ( !attrValue.isValid() || attrValue.isNull() )
2185 #ifdef OGRNullMarker 2186 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2197 switch ( field.
type() )
2200 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2202 case QVariant::LongLong:
2203 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2205 case QVariant::Bool:
2206 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2208 case QVariant::String:
2209 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2211 case QVariant::Double:
2212 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2214 case QVariant::Date:
2215 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2216 attrValue.toDate().year(),
2217 attrValue.toDate().month(),
2218 attrValue.toDate().day(),
2221 case QVariant::DateTime:
2224 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2228 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2229 attrValue.toDateTime().date().year(),
2230 attrValue.toDateTime().date().month(),
2231 attrValue.toDateTime().date().day(),
2232 attrValue.toDateTime().time().hour(),
2233 attrValue.toDateTime().time().minute(),
2234 attrValue.toDateTime().time().second(),
2238 case QVariant::Time:
2241 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2245 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2247 attrValue.toTime().hour(),
2248 attrValue.toTime().minute(),
2249 attrValue.toTime().second(),
2253 case QVariant::Invalid:
2256 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
2259 .arg( attrValue.typeName(),
2260 attrValue.toString() );
2283 OGRGeometryH mGeom2 =
nullptr;
2329 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2330 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2336 QByteArray wkb( geom.
asWkb() );
2337 OGRErr err = OGR_G_ImportFromWkb( mGeom2, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2338 if ( err != OGRERR_NONE )
2340 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2341 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2348 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
2352 QByteArray wkb( geom.
asWkb() );
2354 OGRErr err = OGR_G_ImportFromWkb( ogrGeom, reinterpret_cast<unsigned char *>( const_cast<char *>( wkb.constData() ) ), wkb.length() );
2355 if ( err != OGRERR_NONE )
2357 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
2358 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2365 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
2380 for (
int i = 0; i < attributes.size(); i++ )
2382 if ( omap.find( i ) != omap.end() )
2387 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
2389 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
2391 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
2401 if ( mUsingTransaction )
2403 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
2405 QgsDebugMsg( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
2413 OSRDestroySpatialReference(
mOgrRef );
2419 const QString &fileName,
2420 const QString &fileEncoding,
2422 const QString &driverName,
2425 const QStringList &datasourceOptions,
2426 const QStringList &layerOptions,
2427 bool skipAttributeCreation,
2428 QString *newFilename,
2440 if ( destCRS.
isValid() && layer )
2448 errorMessage, datasourceOptions, layerOptions, skipAttributeCreation,
2449 newFilename, symbologyExport, symbologyScale, filterExtent,
2450 overrideGeometryType, forceMulti, includeZ, attributes,
2451 fieldValueConverter, newLayer );
2456 const QString &fileName,
2457 const QString &fileEncoding,
2459 const QString &driverName,
2462 const QStringList &datasourceOptions,
2463 const QStringList &layerOptions,
2464 bool skipAttributeCreation,
2465 QString *newFilename,
2493 return writeAsVectorFormat( layer, fileName, options, newFilename, errorMessage, newLayer );
2498 : driverName( QStringLiteral(
"GPKG" ) )
2506 if ( !layer || !layer->
isValid() )
2514 details.sourceCrs = layer->
crs();
2515 details.sourceWkbType = layer->
wkbType();
2516 details.sourceFields = layer->
fields();
2525 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
2533 details.geometryTypeScanIterator = layer->
getFeatures( req );
2537 details.renderContext.setExpressionContext( details.expressionContext );
2538 details.renderContext.setRendererScale( options.
symbologyScale );
2540 details.shallTransform =
false;
2545 details.shallTransform =
true;
2550 details.outputCrs = details.sourceCrs;
2553 details.destWkbType = details.sourceWkbType;
2567 details.attributes.clear();
2568 else if ( details.attributes.isEmpty() )
2570 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
2571 for (
int idx : allAttributes )
2573 QgsField fld = details.sourceFields.at( idx );
2574 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
2576 details.attributes.append( idx );
2580 if ( !details.attributes.isEmpty() )
2582 for (
int attrIdx : qgis::as_const( details.attributes ) )
2584 details.outputFields.append( details.sourceFields.at( attrIdx ) );
2590 if ( details.providerType == QLatin1String(
"spatialite" ) )
2592 for (
int i = 0; i < details.outputFields.size(); i++ )
2594 if ( details.outputFields.at( i ).type() == QVariant::LongLong )
2598 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
2600 details.outputFields[i].setType( QVariant::Int );
2608 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
2618 bool useFilterRect =
true;
2619 if ( details.shallTransform )
2628 useFilterRect =
false;
2631 if ( useFilterRect )
2633 req.setFilterRect( filterRect );
2637 details.filterRectEngine->prepareGeometry();
2639 details.sourceFeatureIterator = layer->
getFeatures( req );
2649 int lastProgressReport = 0;
2650 long total = details.featureCount;
2653 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
2655 QString srcFileName( details.providerUriParams.value( QLatin1String(
"path" ) ).toString() );
2656 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
2660 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
2661 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
2662 options.
driverName == QLatin1String(
"SQLite" ) ) &&
2663 options.
layerName != details.providerUriParams.value( QLatin1String(
"layerName" ) ) ) )
2666 *errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
2686 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
2687 if ( newProgress != lastProgressReport )
2689 lastProgressReport = newProgress;
2704 std::unique_ptr< QgsVectorFileWriter > writer =
2705 qgis::make_unique< QgsVectorFileWriter >( fileName,
2706 options.
fileEncoding, details.outputFields, destWkbType,
2728 *errorMessage = writer->errorMessage();
2734 errorMessage->clear();
2756 int n = 0, errors = 0;
2765 writer->startRender( details.renderer.get(), details.sourceFields );
2767 writer->resetMap( details.attributes );
2769 writer->mFields = details.sourceFields;
2773 int initialProgress = lastProgressReport;
2774 while ( details.sourceFeatureIterator.nextFeature( fet ) )
2785 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
2786 if ( newProgress < 100 && newProgress != lastProgressReport )
2788 lastProgressReport = newProgress;
2793 if ( details.shallTransform )
2806 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
2807 .arg( fet.
id() ).arg( e.
what() );
2810 *errorMessage = msg;
2824 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
2827 if ( err !=
NoError && errorMessage )
2829 if ( errorMessage->isEmpty() )
2831 *errorMessage = QObject::tr(
"Feature write errors:" );
2833 *errorMessage +=
'\n' + writer->errorMessage();
2837 if ( errors > 1000 )
2841 *errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
2851 writer->stopRender();
2853 if ( errors > 0 && errorMessage && n > 0 )
2855 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
2863 const QString &fileName,
2865 QString *newFilename,
2866 QString *errorMessage,
2869 QgsVectorFileWriter::PreparedWriterDetails details;
2870 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
2874 return writeAsVectorFormat( details, fileName, options, newFilename, errorMessage, newLayer );
2880 QFileInfo fi( fileName );
2881 QDir dir = fi.dir();
2884 const char *suffixes[] = {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj" };
2885 for ( std::size_t i = 0; i <
sizeof( suffixes ) /
sizeof( *suffixes ); i++ )
2887 filter << fi.completeBaseName() + suffixes[i];
2891 Q_FOREACH (
const QString &file, dir.entryList( filter ) )
2893 QFile f( dir.canonicalPath() +
'/' + file );
2896 QgsDebugMsg( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
2912 QList< FilterFormatDetails > results;
2915 int const drvCount = OGRGetDriverCount();
2917 for (
int i = 0; i < drvCount; ++i )
2919 OGRSFDriverH drv = OGRGetDriver( i );
2922 QString drvName = OGR_Dr_GetName( drv );
2924 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(2,3,0) 2925 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
2926 char **metadata =
nullptr;
2929 metadata = GDALGetMetadata( gdalDriver,
nullptr );
2932 bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL,
false );
2934 bool nonSpatialFormat = ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) );
2937 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
2942 if ( nonSpatialFormat )
2947 if ( filterString.isEmpty() )
2954 globs = metadata.
glob.toLower().split(
' ' );
2960 details.
globs = globs;
2971 if ( a.
driverName == QLatin1String(
"GPKG" ) )
2973 else if ( b.driverName == QLatin1String(
"GPKG" ) )
2975 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
2977 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
2981 return a.
filterString.toLower().localeAwareCompare( b.filterString.toLower() ) < 0;
2990 QSet< QString > extensions;
2992 const QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
2996 for (
const QString &glob : format.globs )
2998 const QRegularExpressionMatch match = rx.match( glob );
2999 if ( !match.hasMatch() )
3002 const QString matched = match.captured( 1 );
3003 extensions.insert( matched );
3007 QStringList extensionList = extensions.toList();
3009 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool 3013 if ( a == QLatin1String(
"gpkg" ) )
3015 else if ( b == QLatin1String(
"gpkg" ) )
3017 else if ( a == QLatin1String(
"shp" ) )
3019 else if ( b == QLatin1String(
"shp" ) )
3023 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
3026 return extensionList;
3031 QList< QgsVectorFileWriter::DriverDetails > results;
3034 const int drvCount = OGRGetDriverCount();
3036 QStringList writableDrivers;
3037 for (
int i = 0; i < drvCount; ++i )
3039 OGRSFDriverH drv = OGRGetDriver( i );
3042 QString drvName = OGR_Dr_GetName( drv );
3048 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
3052 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
3054 writableDrivers << QStringLiteral(
"DBF file" );
3056 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3059 if ( drvName == QLatin1String(
"MapInfo File" ) )
3061 writableDrivers << QStringLiteral(
"MapInfo MIF" );
3063 else if ( drvName == QLatin1String(
"SQLite" ) )
3070 QString option = QStringLiteral(
"SPATIALITE=YES" );
3071 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
3072 OGRSFDriverH poDriver;
3074 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
3077 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
3080 writableDrivers << QStringLiteral(
"SpatiaLite" );
3081 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
3084 CPLFree( options[0] );
3086 writableDrivers << drvName;
3091 results.reserve( writableDrivers.count() );
3092 for (
const QString &drvName : qgis::as_const( writableDrivers ) )
3108 if ( a.
driverName == QLatin1String(
"GPKG" ) )
3110 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3112 else if ( a.
driverName == QLatin1String(
"ESRI Shapefile" ) )
3114 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3118 return a.
longName.toLower().localeAwareCompare( b.longName.toLower() ) < 0;
3125 QString ext = extension.trimmed();
3126 if ( ext.isEmpty() )
3129 if ( ext.startsWith(
'.' ) )
3133 int const drvCount = GDALGetDriverCount();
3135 for (
int i = 0; i < drvCount; ++i )
3137 GDALDriverH drv = GDALGetDriver( i );
3141 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE,
false ) && CSLFetchBoolean( driverMetadata, GDAL_DCAP_VECTOR,
false ) )
3143 QString drvName = GDALGetDriverShortName( drv );
3144 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
3146 Q_FOREACH (
const QString &driver, driverExtensions )
3148 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
3159 QString filterString;
3163 if ( !filterString.isEmpty() )
3164 filterString += QLatin1String(
";;" );
3166 filterString += details.filterString;
3168 return filterString;
3177 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
3178 metadata.
glob.toLower(),
3179 metadata.
glob.toUpper() );
3184 if ( codecName == QLatin1String(
"System" ) )
3185 return QStringLiteral(
"LDID/0" );
3187 QRegExp re = QRegExp( QString(
"(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
3188 if ( re.exactMatch( codecName ) )
3190 QString
c = re.cap( 2 ).remove(
'-' );
3192 c.toInt( &isNumber );
3220 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
3221 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
3224 int nTotalLevels = 0;
3226 QgsSymbolList::iterator symbolIt = symbolList.begin();
3227 for ( ; symbolIt != symbolList.end(); ++symbolIt )
3229 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3230 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
3232 int nLevels = ( *symbolIt )->symbolLayerCount();
3233 for (
int i = 0; i < nLevels; ++i )
3235 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
3236 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
3237 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
3241 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
3247 if ( !details.renderer )
3250 mRenderContext.expressionContext() = details.expressionContext;
3252 QHash< QgsSymbol *, QList<QgsFeature> > features;
3261 startRender( details.renderer.get(), details.sourceFields );
3272 if ( fet.hasGeometry() )
3276 fet.setGeometry( g );
3281 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
3285 *errorMessage = msg;
3290 mRenderContext.expressionContext().setFeature( fet );
3292 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
3293 if ( !featureSymbol )
3298 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
3299 if ( it == features.end() )
3301 it = features.insert( featureSymbol, QList<QgsFeature>() );
3303 it.value().append( fet );
3308 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
3309 for (
int i = 0; i < symbols.count(); i++ )
3315 if ( level < 0 || level >= 1000 )
3318 while ( level >= levels.count() )
3320 levels[level].append( item );
3325 int nTotalFeatures = 0;
3328 for (
int l = 0; l < levels.count(); l++ )
3331 for (
int i = 0; i < level.count(); i++ )
3334 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
3335 if ( levelIt == features.end() )
3341 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3342 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
3344 int llayer = item.
layer();
3345 QList<QgsFeature> &featureList = levelIt.value();
3346 QList<QgsFeature>::iterator featureIt = featureList.begin();
3347 for ( ; featureIt != featureList.end(); ++featureIt )
3357 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
3358 if ( !styleString.isEmpty() )
3360 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
3361 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
3372 if ( nErrors > 0 && errorMessage )
3374 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
3391 return 1000 / scale;
3408 return scale / 1000;
3416 mRenderer = createSymbologyRenderer( sourceRenderer );
3422 mRenderer->startRender( mRenderContext, fields );
3425 void QgsVectorFileWriter::stopRender()
3432 mRenderer->stopRender( mRenderContext );
3435 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const 3441 if ( !sourceRenderer )
3446 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
3453 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
3454 for (
const QString &attr : rendererAttributes )
3459 attList.append( index );
3465 QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
3468 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
3470 for ( it = options.constBegin(); it != options.constEnd(); ++it )
3473 switch ( option->
type )
3480 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
3490 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3500 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
3509 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
3520 OGRSFDriverH hDriver =
nullptr;
3524 QString drvName = OGR_Dr_GetName( hDriver );
3525 QgsVectorFileWriter::EditionCapabilities caps =
nullptr;
3526 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
3531 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
3534 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
3538 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
3541 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
3544 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
3547 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
3558 const QString &layerNameIn )
3560 OGRSFDriverH hDriver =
nullptr;
3566 if ( layerName.isEmpty() )
3567 layerName = QFileInfo( datasetName ).baseName();
3569 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3578 OGRSFDriverH hDriver =
nullptr;
3582 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
3588 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
3589 Q_FOREACH (
int idx, attributes )
3592 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.
Append features to existing layer, but do not create new fields.
Wrapper for iterator of features from vector data provider or vector layer.
bool isCanceled() const
Tells whether the operation has been canceled already.
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.
bool isValid() const
Returns the status of the layer.
QgsVectorFileWriter::SymbologyExport symbologyExport() const
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.
double symbologyScale() const
Returns the reference scale for output.
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.
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.
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) ...
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
QList< QgsFeature > QgsFeatureList
SymbologyExport mSymbologyExport
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
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)
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...
bool usingSymbolLevels() const
QString toWkt() const
Returns a WKT representation of this CRS.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
#define Q_NOWARN_DEPRECATED_PUSH
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
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)
Returns the components (e.g.
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
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1)
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. ...
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
Create or overwrite file.
~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()
void setSymbologyScale(double scale)
Set reference scale for output.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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
QString typeName() const
Gets the field type.
QgsFields fields() const FINAL
Returns the list of fields of 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.
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.
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).
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.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
Create or overwrite layer.
long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
int count() const
Returns number of items.
int renderingPass() const
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.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
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...
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
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
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.
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
DistanceUnit
Units of distance.
QString errorMessage()
Retrieves error message.
#define Q_NOWARN_DEPRECATED_POP
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString providerType() const
Returns the provider type for this layer.
Contains information about the context of a rendering operation.
QByteArray asWkb() const
Export the geometry to WKB.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
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.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QList< QgsSymbolLevelItem > QgsSymbolLevel
bool skipAttributeCreation
Only write geometries.
double symbologyScale
Scale of symbology.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
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 hasGeometry() const
Returns true if the feature has an associated geometry.
int size() const
Returns number of items.
#define FID_TO_NUMBER(fid)
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prf)
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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query 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.
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 PostgreSQL/RDBMS datasource URI.
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.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Writing was interrupted by manual cancellation.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
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)
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.