24#include <cpl_string.h>
29#include <ogr_srs_api.h>
52#include <QJsonDocument>
55#include <QRegularExpression>
61using namespace Qt::StringLiterals;
79 const QString &vectorFileName,
80 const QString &fileEncoding,
84 const QString &driverName,
85 const QStringList &datasourceOptions,
86 const QStringList &layerOptions,
99 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr, QString(),
CreateOrOverwriteFile, newLayer, sinkFlags, transformContext, fieldNameSource,
nullptr );
103 const QString &vectorFileName,
104 const QString &fileEncoding,
108 const QString &driverName,
109 const QStringList &datasourceOptions,
110 const QStringList &layerOptions,
111 QString *newFilename,
114 const QString &layerName,
120 bool includeConstraints,
121 bool setFieldDomains,
131 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName, datasourceOptions, layerOptions, newFilename, fieldValueConverter, layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource, sourceDatabaseProviderConnection );
135 const QString &fileName,
142 QString *newFilename,
174 if ( driverName ==
"MapInfo MIF"_L1 )
178 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
182 CSLConstList
driverMetadata = GDALGetMetadata( gdalDriver,
nullptr );
186#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
187 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
189 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
193void QgsVectorFileWriter::init(
194 QString vectorFileName,
195 QString fileEncoding,
199 const QString &driverName,
200 QStringList datasourceOptions,
201 QStringList layerOptions,
202 QString *newFilename,
203 FieldValueConverter *fieldValueConverter,
204 const QString &layerNameIn,
205 ActionOnExistingFile action,
209 FieldNameSource fieldNameSource,
213#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 5, 0 )
214 ( void ) sourceDatabaseProviderConnection;
219 if ( vectorFileName.isEmpty() )
226 if ( driverName ==
"MapInfo MIF"_L1 )
230 else if ( driverName ==
"SpatiaLite"_L1 )
233 if ( !datasourceOptions.contains( u
"SPATIALITE=YES"_s ) )
235 datasourceOptions.append( u
"SPATIALITE=YES"_s );
238 else if ( driverName ==
"DBF file"_L1 )
241 if ( !layerOptions.contains( u
"SHPT=NULL"_s ) )
243 layerOptions.append( u
"SHPT=NULL"_s );
245 srs = QgsCoordinateReferenceSystem();
252#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 3, 1 )
253 QString fidFieldName;
256 for (
const QString &layerOption : layerOptions )
258 if ( layerOption.startsWith(
"FID="_L1 ) )
260 fidFieldName = layerOption.mid( 4 );
264 if ( fidFieldName.isEmpty() )
265 fidFieldName = u
"fid"_s;
270 OGRSFDriverH poDriver;
273 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
277 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" ).arg( driverName, QString::fromUtf8( CPLGetLastErrorMsg() ) );
282 mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME,
nullptr ) );
289 if ( layerOptions.join( QString() ).toUpper().indexOf(
"ENCODING="_L1 ) == -1 )
294 if ( driverName ==
"ESRI Shapefile"_L1 && !vectorFileName.endsWith(
".shp"_L1, Qt::CaseInsensitive ) )
296 vectorFileName +=
".shp"_L1;
298 else if ( driverName ==
"DBF file"_L1 && !vectorFileName.endsWith(
".dbf"_L1, Qt::CaseInsensitive ) )
300 vectorFileName +=
".dbf"_L1;
310 QStringList allExts = metadata.glob.split(
' ', Qt::SkipEmptyParts );
312 const auto constAllExts = allExts;
313 for (
const QString &ext : constAllExts )
316 if ( vectorFileName.endsWith( ext.mid( 1 ), Qt::CaseInsensitive ) )
325 allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
326 vectorFileName +=
'.' + allExts[0];
332 if ( vectorFileName.endsWith(
".gdb"_L1, Qt::CaseInsensitive ) )
334 QDir dir( vectorFileName );
337 QFileInfoList fileList = dir.entryInfoList( QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
338 const auto constFileList = fileList;
339 for (
const QFileInfo &info : constFileList )
341 QFile::remove( info.absoluteFilePath() );
344 QDir().rmdir( vectorFileName );
348 QFile::remove( vectorFileName );
353 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
355 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
357 QgsDebugMsgLevel( u
"forced %1 encoding for %2"_s.arg( metadata.compulsoryEncoding, driverName ), 2 );
358 fileEncoding = metadata.compulsoryEncoding;
362 char **options =
nullptr;
363 if ( !datasourceOptions.isEmpty() )
365 options =
new char *[datasourceOptions.size() + 1];
366 for (
int i = 0; i < datasourceOptions.size(); i++ )
369 options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
371 options[datasourceOptions.size()] =
nullptr;
376 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
378 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
382 for (
int i = 0; i < datasourceOptions.size(); i++ )
383 CPLFree( options[i] );
392 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
394 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
398 QString layerName( layerNameIn );
399 if ( layerName.isEmpty() )
400 layerName = QFileInfo( vectorFileName ).baseName();
404 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
405 for (
int i = 0; i < layer_count; i++ )
407 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
408 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
410 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
413 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
431 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
434 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
436 QgsSettings settings;
437 QString enc = settings.
value( u
"UI/encoding"_s,
"System" ).toString();
438 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
442 mCodec = QTextCodec::codecForLocale();
448 if ( driverName ==
"KML"_L1 || driverName ==
"LIBKML"_L1 || driverName ==
"GPX"_L1 )
450 if ( srs.
authid() !=
"EPSG:4326"_L1 )
454 mCoordinateTransform = std::make_unique<QgsCoordinateTransform>( srs, wgs84, transformContext );
471 int optIndex = layerOptions.indexOf(
"FEATURE_DATASET="_L1 );
472 if ( optIndex != -1 )
474 layerOptions.removeAt( optIndex );
477 if ( !layerOptions.isEmpty() )
479 options =
new char *[layerOptions.size() + 1];
480 for (
int i = 0; i < layerOptions.size(); i++ )
483 options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
485 options[layerOptions.size()] =
nullptr;
489 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
493 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
496 *newLayer = OGR_L_GetName(
mLayer );
497 if ( driverName ==
"GPX"_L1 )
504 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) && !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
506 *newLayer = u
"waypoints"_s;
513 const char *pszForceGPXTrack = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
514 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
515 *newLayer = u
"tracks"_s;
517 *newLayer = u
"routes"_s;
523 const char *pszForceGPXRoute = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
524 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
525 *newLayer = u
"routes"_s;
527 *newLayer = u
"tracks"_s;
537 else if ( driverName ==
"DGN"_L1 )
539 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
543 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
548 for (
int i = 0; i < layerOptions.size(); i++ )
549 CPLFree( options[i] );
558 QString layerName = vectorFileName.left( vectorFileName.indexOf(
".shp"_L1, Qt::CaseInsensitive ) );
559 QFile prjFile( layerName +
".qpj" );
560 if ( prjFile.exists() )
568 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
570 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
575 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
585 QSet<int> existingIdxs;
589#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
590 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
592 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
593 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
597 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
601 CSLDestroy( papszTokens );
611#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 5, 0 )
612 QSet<QString> existingDestDomainNames;
613 if ( sourceDatabaseProviderConnection )
615 char **domainNames = GDALDatasetGetFieldDomainNames(
mDS.get(),
nullptr );
616 for (
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
618 existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
620 CSLDestroy( domainNames );
623#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 6, 0 )
624 QSet< QString > usedAlternativeNames;
627 const QString ogrFidColumnName { OGR_L_GetFIDColumn(
mLayer ) };
628 const int fidNameIndex = OGR_FD_GetFieldIndex( defn, ogrFidColumnName.toUtf8() );
631 const bool promoteFidColumnToAttribute = !ogrFidColumnName.isEmpty() && fidNameIndex < 0 && fields.
lookupField( ogrFidColumnName ) >= 0;
632 int offsetRoomForFid = promoteFidColumnToAttribute ? 1 : 0;
634 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
636 QgsField attrField = fields.
at( fldIdx );
638 if ( fieldValueConverter )
640 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
645 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
655 switch ( fieldNameSource )
658 name = attrField.
name();
662 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
666 OGRFieldType ogrType = OFTString;
667 OGRFieldSubType ogrSubType = OFSTNone;
668 int ogrWidth = attrField.
length();
669 int ogrPrecision = attrField.
precision();
670 if ( ogrPrecision > 0 )
673 switch ( attrField.
type() )
675 case QMetaType::Type::LongLong:
677 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
678 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
679 ogrType = OFTInteger64;
682 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
686 case QMetaType::Type::QString:
688 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName ==
"ESRI Shapefile"_L1 )
692 case QMetaType::Type::Int:
693 ogrType = OFTInteger;
694 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
698 case QMetaType::Type::Bool:
699 ogrType = OFTInteger;
700 ogrSubType = OFSTBoolean;
705 case QMetaType::Type::Double:
706#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 3, 1 )
707 if (
mOgrDriverName ==
"GPKG"_L1 && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
710 ogrType = OFTInteger64;
717 case QMetaType::Type::QDate:
721 case QMetaType::Type::QTime:
733 case QMetaType::Type::QDateTime:
741 ogrType = OFTDateTime;
745 case QMetaType::Type::QByteArray:
749 case QMetaType::Type::QStringList:
755 ogrSubType = OFSTJSON;
759 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
760 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
762 ogrType = OFTStringList;
763 mSupportedListSubTypes.insert( QMetaType::Type::QString );
773 case QMetaType::Type::QVariantMap:
776 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
777 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
780 ogrSubType = OFSTJSON;
788 case QMetaType::Type::QVariantList:
793 ogrSubType = OFSTJSON;
798 if ( attrField.
subType() == QMetaType::Type::QString )
800 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
801 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
803 ogrType = OFTStringList;
804 mSupportedListSubTypes.insert( QMetaType::Type::QString );
813 else if ( attrField.
subType() == QMetaType::Type::Int )
815 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
816 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
818 ogrType = OFTIntegerList;
819 mSupportedListSubTypes.insert( QMetaType::Type::Int );
828 else if ( attrField.
subType() == QMetaType::Type::Double )
830 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
831 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
833 ogrType = OFTRealList;
834 mSupportedListSubTypes.insert( QMetaType::Type::Double );
843 else if ( attrField.
subType() == QMetaType::Type::LongLong )
845 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
846 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
848 ogrType = OFTInteger64List;
849 mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
863 mErrorMessage = QObject::tr(
"Unsupported type for field %1" ).arg( attrField.
name() );
868 if (
mOgrDriverName ==
"SQLite"_L1 && name.compare(
"ogc_fid"_L1, Qt::CaseInsensitive ) == 0 )
871 for ( i = 0; i < 10; i++ )
873 name = u
"ogc_fid%1"_s.arg( i );
876 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
879 if ( j == fields.
size() )
885 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
890 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
897 OGR_Fld_SetWidth( fld.get(), ogrWidth );
900 if ( ogrPrecision >= 0 )
902 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
905 if ( ogrSubType != OFSTNone )
906 OGR_Fld_SetSubType( fld.get(), ogrSubType );
908#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 6, 0 )
909 if ( !attrField.
alias().isEmpty() )
911 QString alternativeName = attrField.
alias();
913 while ( usedAlternativeNames.contains( alternativeName ) )
916 alternativeName = attrField.
alias() + u
" (%1)"_s.arg( ++counter );
918 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( alternativeName ).constData() );
919 usedAlternativeNames.insert( alternativeName );
922#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
923 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
930 OGR_Fld_SetNullable( fld.get(),
false );
934 OGR_Fld_SetUnique( fld.get(),
true );
937#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 5, 0 )
941 if ( !domainName.isEmpty() )
943 bool canSetFieldDomainName =
false;
944 if ( existingDestDomainNames.contains( domainName ) )
948 canSetFieldDomainName =
true;
950 else if ( GDALDatasetTestCapability(
mDS.get(), ODsCAddFieldDomain ) )
960 std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
966 char *pszFailureReason =
nullptr;
967 if ( GDALDatasetAddFieldDomain(
mDS.get(), hFieldDomain, &pszFailureReason ) )
969 existingDestDomainNames.insert( domainName );
970 canSetFieldDomainName =
true;
974 QgsDebugError( u
"cannot create field domain: %1"_s.arg( pszFailureReason ) );
976 CPLFree( pszFailureReason );
977 OGR_FldDomain_Destroy( hFieldDomain );
981 catch ( QgsProviderConnectionException & )
983 QgsDebugError( u
"Cannot retrieve field domain: %1"_s.arg( domainName ) );
986 if ( canSetFieldDomainName )
988 OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
995 QgsDebugMsgLevel(
"creating field " + attrField.
name() +
" type " + QString( QVariant::typeToName( attrField.
type() ) ) +
" width " + QString::number( ogrWidth ) +
" precision " + QString::number( ogrPrecision ), 2 );
996 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
999 mErrorMessage = QObject::tr(
"Creation of field %1 (%2) failed (OGR error: %3)" ).arg( attrField.
name(), QVariant::typeToName( attrField.
type() ), QString::fromUtf8( CPLGetLastErrorMsg() ) );
1004 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1005 QgsDebugMsgLevel( u
"returned field index for %1: %2"_s.arg( name ).arg( ogrIdx ), 2 );
1006 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
1009 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
1014 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" ).arg( attrField.
name(), QString::fromUtf8( CPLGetLastErrorMsg() ) );
1020 existingIdxs.insert( ogrIdx );
1023 if ( promoteFidColumnToAttribute )
1025 if ( ogrFidColumnName.compare( attrField.
name(), Qt::CaseInsensitive ) == 0 )
1028 offsetRoomForFid = 0;
1033 ogrIdx += offsetRoomForFid;
1044 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
1046 QgsField attrField = fields.
at( fldIdx );
1047 QString name( attrField.
name() );
1048 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1077 *newFilename = vectorFileName;
1080 mUsingTransaction =
true;
1081 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
1083 mUsingTransaction =
false;
1093class QgsVectorFileWriterMetadataContainer
1096 QgsVectorFileWriterMetadataContainer()
1098 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
1099 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
1102 datasetOptions.clear();
1103 layerOptions.clear();
1105 layerOptions.insert(
1108 QObject::tr(
"Compression method." ),
1109 QStringList() << u
"UNCOMPRESSED"_s << u
"ZSTD"_s << u
"LZ4"_s,
1115 layerOptions.insert(
1116 u
"GEOMETRY_ENCODING"_s,
1118 QObject::tr(
"Geometry encoding." ),
1119 QStringList() << u
"GEOARROW"_s << u
"WKB"_s << u
"WKT"_s,
1125 layerOptions.insert(
1128 QObject::tr(
"Maximum number of rows per batch." ),
1133 layerOptions.insert(
1136 QObject::tr(
"Name for the feature identifier column" ),
1141 layerOptions.insert(
1144 QObject::tr(
"Name for the geometry column" ),
1149 driverMetadata.insert( u
"Arrow"_s,
QgsVectorFileWriter::MetaData( u
"(Geo)Arrow"_s, QObject::tr(
"(Geo)Arrow" ), u
"*.arrow *.feather *.arrows *.ipc"_s, u
"arrow"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1152 datasetOptions.clear();
1153 layerOptions.clear();
1155 driverMetadata.insert( u
"AVCE00"_s,
QgsVectorFileWriter::MetaData( u
"Arc/Info ASCII Coverage"_s, QObject::tr(
"Arc/Info ASCII Coverage" ), u
"*.e00"_s, u
"e00"_s, datasetOptions, layerOptions ) );
1158 datasetOptions.clear();
1159 layerOptions.clear();
1161 layerOptions.insert(
1165 "By default when creating new .csv files they "
1166 "are created with the line termination conventions "
1167 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1168 "This may be overridden through the use of the LINEFORMAT option."
1170 QStringList() << u
"CRLF"_s << u
"LF"_s,
1176 layerOptions.insert(
1180 "By default, the geometry of a feature written to a .csv file is discarded. "
1181 "It is possible to export the geometry in its WKT representation by "
1182 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1183 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1184 "or GEOMETRY=AS_YX."
1186 QStringList() << u
"AS_WKT"_s << u
"AS_XYZ"_s << u
"AS_XY"_s << u
"AS_YX"_s,
1192 layerOptions.insert(
1195 QObject::tr(
"Name of geometry column. Only used if GEOMETRY=AS_WKT. Defaults to 'WKT'." ),
1200 layerOptions.insert(
1204 "Create the associated .csvt file to describe the type of each "
1205 "column of the layer and its optional width and precision. "
1206 "This option also creates a .prj file which stores coordinate system information."
1212 layerOptions.insert(
1215 QObject::tr(
"Field separator character." ),
1221#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
1229 layerOptions.insert(
1230 u
"STRING_QUOTING"_s,
1232 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1233 QStringList() << u
"IF_NEEDED"_s << u
"IF_AMBIGUOUS"_s << u
"ALWAYS"_s,
1238 layerOptions.insert(
1241 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1246#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
1247 layerOptions.insert(
1250 QObject::tr(
"Whether to write a header line with the field names." ),
1256 driverMetadata.insert( u
"CSV"_s,
QgsVectorFileWriter::MetaData( u
"Comma Separated Value [CSV]"_s, QObject::tr(
"Comma Separated Value [CSV]" ), u
"*.csv"_s, u
"csv"_s, datasetOptions, layerOptions ) );
1259 datasetOptions.clear();
1260 layerOptions.clear();
1262 driverMetadata.insert( u
"FlatGeobuf"_s,
QgsVectorFileWriter::MetaData( u
"FlatGeobuf"_s, QObject::tr(
"FlatGeobuf" ), u
"*.fgb"_s, u
"fgb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1265 datasetOptions.clear();
1266 layerOptions.clear();
1268 layerOptions.insert(
1272 "Override the type of shapefile created. "
1273 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1274 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1275 "MULTIPOINTZ for 3D;"
1278 " POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1279 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1282 + QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." )
1301 << u
"MULTIPOINTZM"_s
1313 QObject::tr(
"Set the encoding value in the DBF file. "
1314 "The default value is LDID/87. It is not clear "
1315 "what other values may be appropriate." ),
1322 layerOptions.insert(
1325 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1330 driverMetadata.insert( u
"ESRI"_s,
QgsVectorFileWriter::MetaData( u
"ESRI Shapefile"_s, QObject::tr(
"ESRI Shapefile" ), u
"*.shp"_s, u
"shp"_s, datasetOptions, layerOptions ) );
1333 datasetOptions.clear();
1334 layerOptions.clear();
1336 driverMetadata.insert( u
"DBF File"_s,
QgsVectorFileWriter::MetaData( u
"DBF File"_s, QObject::tr(
"DBF File" ), u
"*.dbf"_s, u
"dbf"_s, datasetOptions, layerOptions ) );
1339 datasetOptions.clear();
1340 layerOptions.clear();
1342 layerOptions.insert(
1346 "Set to YES to write a bbox property with the bounding box "
1347 "of the geometries at the feature and feature collection level."
1353 layerOptions.insert(
1354 u
"COORDINATE_PRECISION"_s,
1357 "Maximum number of figures after decimal separator to write in coordinates. "
1358 "Defaults to 15. Truncation will occur to remove trailing zeros."
1364 layerOptions.insert(
1368 "Whether to use RFC 7946 standard. "
1369 "If disabled GeoJSON 2008 initial version will be used. "
1370 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)"
1376 driverMetadata.insert( u
"GeoJSON"_s,
QgsVectorFileWriter::MetaData( u
"GeoJSON"_s, QObject::tr(
"GeoJSON" ), u
"*.geojson"_s, u
"geojson"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1379 datasetOptions.clear();
1380 layerOptions.clear();
1382 layerOptions.insert(
1383 u
"COORDINATE_PRECISION"_s,
1386 "Maximum number of figures after decimal separator to write in coordinates. "
1387 "Defaults to 15. Truncation will occur to remove trailing zeros."
1393 layerOptions.insert(
1397 "Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1398 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1399 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)."
1406 .insert( u
"GeoJSONSeq"_s,
QgsVectorFileWriter::MetaData( u
"GeoJSON - Newline Delimited"_s, QObject::tr(
"GeoJSON - Newline Delimited" ), u
"*.geojsonl *.geojsons *.json"_s, u
"geojsonl geojsons json"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1409 datasetOptions.clear();
1410 layerOptions.clear();
1412 datasetOptions.insert(
1416 "whether the document must be in RSS 2.0 or Atom 1.0 format. "
1417 "Default value : RSS"
1419 QStringList() << u
"RSS"_s << u
"ATOM"_s,
1424 datasetOptions.insert(
1428 "The encoding of location information. Default value : SIMPLE. "
1429 "W3C_GEO only supports point geometries. "
1430 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates."
1432 QStringList() << u
"SIMPLE"_s << u
"GML"_s << u
"W3C_GEO"_s,
1437 datasetOptions.insert(
1438 u
"USE_EXTENSIONS"_s,
1441 "If defined to YES, extension fields will be written. "
1442 "If the field name not found in the base schema matches "
1443 "the foo_bar pattern, foo will be considered as the namespace "
1444 "of the element, and a <foo:bar> element will be written. "
1445 "Otherwise, elements will be written in the <ogr:> namespace."
1451 datasetOptions.insert(
1452 u
"WRITE_HEADER_AND_FOOTER"_s,
1455 "If defined to NO, only <entry> or <item> elements will be written. "
1456 "The user will have to provide the appropriate header and footer of the document."
1462 datasetOptions.insert(
1466 "XML content that will be put between the <channel> element and the "
1467 "first <item> element for a RSS document, or between the xml tag and "
1468 "the first <entry> element for an Atom document."
1474 datasetOptions.insert(
1478 "Value put inside the <title> element in the header. "
1479 "If not provided, a dummy value will be used as that element is compulsory."
1485 datasetOptions.insert(
1489 "Value put inside the <description> element in the header. "
1490 "If not provided, a dummy value will be used as that element is compulsory."
1496 datasetOptions.insert(
1500 "Value put inside the <link> element in the header. "
1501 "If not provided, a dummy value will be used as that element is compulsory."
1507 datasetOptions.insert(
1511 "Value put inside the <updated> element in the header. "
1512 "Should be formatted as a XML datetime. "
1513 "If not provided, a dummy value will be used as that element is compulsory."
1519 datasetOptions.insert(
1523 "Value put inside the <author><name> element in the header. "
1524 "If not provided, a dummy value will be used as that element is compulsory."
1530 datasetOptions.insert(
1534 "Value put inside the <id> element in the header. "
1535 "If not provided, a dummy value will be used as that element is compulsory."
1541 driverMetadata.insert( u
"GeoRSS"_s,
QgsVectorFileWriter::MetaData( u
"GeoRSS"_s, QObject::tr(
"GeoRSS" ), u
"*.xml"_s, u
"xml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1544 datasetOptions.clear();
1545 layerOptions.clear();
1547 datasetOptions.insert(
1551 "If provided, this URI will be inserted as the schema location. "
1552 "Note that the schema file isn't actually accessed by OGR, so it "
1553 "is up to the user to ensure it will match the schema of the OGR "
1554 "produced GML data file."
1560 datasetOptions.insert(
1564 "This writes a GML application schema file to a corresponding "
1565 ".xsd file (with the same basename). If INTERNAL is used the "
1566 "schema is written within the GML file, but this is experimental "
1567 "and almost certainly not valid XML. "
1568 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)."
1570 QStringList() << u
"EXTERNAL"_s << u
"INTERNAL"_s << u
"OFF"_s,
1575 datasetOptions.insert(
1578 QObject::tr(
"This is the prefix for the application target namespace." ),
1583 datasetOptions.insert(
1587 "Can be set to TRUE to avoid writing the prefix of the "
1588 "application target namespace in the GML file."
1594 datasetOptions.insert(
1595 u
"TARGET_NAMESPACE"_s,
1598 "Defaults to 'http://ogr.maptools.org/'. "
1599 "This is the application target namespace."
1601 u
"http://ogr.maptools.org/"_s
1605 datasetOptions.insert(
1608 QObject::tr(
"GML version to use." ),
1609 QStringList() << u
"GML2"_s << u
"GML3"_s << u
"GML3Deegree"_s << u
"GML3.2"_s,
1614 datasetOptions.insert(
1618 "Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1619 "If YES, SRS with EPSG authority will be written with the "
1620 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1621 "geographic SRS without explicit AXIS order, but that the same "
1622 "SRS authority code imported with ImportFromEPSGA() should be "
1623 "treated as lat/long, then the function will take care of coordinate "
1624 "order swapping. If set to NO, SRS with EPSG authority will be "
1625 "written with the 'EPSG:' prefix, even if they are in lat/long order."
1631 datasetOptions.insert(
1632 u
"WRITE_FEATURE_BOUNDED_BY"_s,
1635 "only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1636 "If set to NO, the <gml:boundedBy> element will not be written for "
1643 datasetOptions.insert(
1644 u
"SPACE_INDENTATION"_s,
1647 "Default to YES. If YES, the output will be indented with spaces "
1648 "for more readability, but at the expense of file size."
1656 .insert( u
"GML"_s,
QgsVectorFileWriter::MetaData( u
"Geography Markup Language [GML]"_s, QObject::tr(
"Geography Markup Language [GML]" ), u
"*.gml"_s, u
"gml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1659 datasetOptions.clear();
1660 layerOptions.clear();
1662 layerOptions.insert(
1665 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1670 layerOptions.insert(
1673 QObject::tr(
"Human-readable description for the layer content" ),
1678 layerOptions.insert(
1681 QObject::tr(
"Name for the feature identifier column" ),
1686 layerOptions.insert(
1689 QObject::tr(
"Name for the geometry column" ),
1694 layerOptions.insert(
1697 QObject::tr(
"If a spatial index must be created." ),
1702 driverMetadata.insert(
1706 QObject::tr(
"GeoPackage" ),
1707#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 7, 0 )
1708 u
"*.gpkg *.gpkg.zip"_s,
1720 datasetOptions.clear();
1721 layerOptions.clear();
1723 driverMetadata.insert( u
"GMT"_s,
QgsVectorFileWriter::MetaData( u
"Generic Mapping Tools [GMT]"_s, QObject::tr(
"Generic Mapping Tools [GMT]" ), u
"*.gmt"_s, u
"gmt"_s, datasetOptions, layerOptions ) );
1726 datasetOptions.clear();
1727 layerOptions.clear();
1729 layerOptions.insert(
1730 u
"FORCE_GPX_TRACK"_s,
1733 "By default when writing a layer whose features are of "
1734 "type wkbLineString, the GPX driver chooses to write "
1735 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1736 "they will be written as tracks."
1742 layerOptions.insert(
1743 u
"FORCE_GPX_ROUTE"_s,
1746 "By default when writing a layer whose features are of "
1747 "type wkbMultiLineString, the GPX driver chooses to write "
1748 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1749 "they will be written as routes, provided that the multilines "
1750 "are composed of only one single line."
1756 datasetOptions.insert(
1757 u
"GPX_USE_EXTENSIONS"_s,
1760 "If GPX_USE_EXTENSIONS=YES is specified, "
1761 "extra fields will be written inside the <extensions> tag."
1767 datasetOptions.insert(
1768 u
"GPX_EXTENSIONS_NS"_s,
1771 "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1772 "is set. The namespace value used for extension tags. By default, 'ogr'."
1778 datasetOptions.insert(
1779 u
"GPX_EXTENSIONS_NS_URL"_s,
1782 "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1783 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'."
1785 u
"http://osgeo.org/gdal"_s
1789 datasetOptions.insert(
1793 "By default files are created with the line termination "
1794 "conventions of the local platform (CR/LF on win32 or LF "
1795 "on all other systems). This may be overridden through use "
1796 "of the LINEFORMAT layer creation option which may have a value "
1797 "of CRLF (DOS format) or LF (Unix format)."
1799 QStringList() << u
"CRLF"_s << u
"LF"_s,
1805 driverMetadata.insert( u
"GPX"_s,
QgsVectorFileWriter::MetaData( u
"GPS eXchange Format [GPX]"_s, QObject::tr(
"GPS eXchange Format [GPX]" ), u
"*.gpx"_s, u
"gpx"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1808 datasetOptions.clear();
1809 layerOptions.clear();
1811 driverMetadata.insert( u
"Interlis 1"_s,
QgsVectorFileWriter::MetaData( u
"INTERLIS 1"_s, QObject::tr(
"INTERLIS 1" ), u
"*.itf *.xml *.ili"_s, u
"ili"_s, datasetOptions, layerOptions ) );
1814 datasetOptions.clear();
1815 layerOptions.clear();
1817 driverMetadata.insert( u
"Interlis 2"_s,
QgsVectorFileWriter::MetaData( u
"INTERLIS 2"_s, QObject::tr(
"INTERLIS 2" ), u
"*.xtf *.xml *.ili"_s, u
"ili"_s, datasetOptions, layerOptions ) );
1820 datasetOptions.clear();
1821 layerOptions.clear();
1823 datasetOptions.insert(
1826 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1831 datasetOptions.insert(
1832 u
"DescriptionField"_s,
1834 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1839 datasetOptions.insert(
1843 "Allows you to specify the AltitudeMode to use for KML geometries. "
1844 "This will only affect 3D geometries and must be one of the valid KML options."
1846 QStringList() << u
"clampToGround"_s << u
"relativeToGround"_s << u
"absolute"_s,
1847 u
"relativeToGround"_s
1851 datasetOptions.insert(
1855 "The DOCUMENT_ID datasource creation option can be used to specified "
1856 "the id of the root <Document> node. The default value is root_doc."
1863 .insert( u
"KML"_s,
QgsVectorFileWriter::MetaData( u
"Keyhole Markup Language [KML]"_s, QObject::tr(
"Keyhole Markup Language [KML]" ), u
"*.kml"_s, u
"kml"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
1866 datasetOptions.clear();
1867 layerOptions.clear();
1869 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions ) {
1870 datasetOptions.insert(
1871 u
"SPATIAL_INDEX_MODE"_s,
1874 "Use this to turn on 'quick spatial index mode'. "
1875 "In this mode writing files can be about 5 times faster, "
1876 "but spatial queries can be up to 30 times slower."
1878 QStringList() << u
"QUICK"_s << u
"OPTIMIZED"_s,
1884 datasetOptions.insert(
1888 "(multiples of 512): Block size for .map files. Defaults "
1889 "to 512. MapInfo 15.2 and above creates .tab files with a "
1890 "blocksize of 16384 bytes. Any MapInfo version should be "
1891 "able to handle block sizes from 512 to 32256."
1896 layerOptions.insert(
1900 "xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1901 "accuracy of the coordinates. Note: the geometry of written "
1902 "features must be within the defined box."
1908 insertMapInfoOptions( datasetOptions, layerOptions );
1910 driverMetadata.insert( u
"MapInfo File"_s, QgsVectorFileWriter::MetaData( u
"Mapinfo"_s, QObject::tr(
"Mapinfo TAB" ), u
"*.tab"_s, u
"tab"_s, datasetOptions, layerOptions ) );
1911 datasetOptions.clear();
1912 layerOptions.clear();
1913 insertMapInfoOptions( datasetOptions, layerOptions );
1916 driverMetadata.insert( u
"MapInfo MIF"_s, QgsVectorFileWriter::MetaData( u
"Mapinfo"_s, QObject::tr(
"Mapinfo MIF" ), u
"*.mif"_s, u
"mif"_s, datasetOptions, layerOptions ) );
1919 datasetOptions.clear();
1920 layerOptions.clear();
1922 datasetOptions.insert(
1924 new QgsVectorFileWriter::BoolOption(
1926 "Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1927 "seed file should be used. This option is ignored if the SEED option is provided."
1933 datasetOptions.insert(
1935 new QgsVectorFileWriter::StringOption(
1936 QObject::tr(
"Override the seed file to use." ),
1941 datasetOptions.insert(
1942 u
"COPY_WHOLE_SEED_FILE"_s,
1943 new QgsVectorFileWriter::BoolOption(
1945 "Indicate whether the whole seed file should be copied. "
1946 "If not, only the first three elements will be copied."
1952 datasetOptions.insert(
1953 u
"COPY_SEED_FILE_COLOR_TABLE"_s,
1954 new QgsVectorFileWriter::BoolOption(
1955 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1960 datasetOptions.insert(
1961 u
"MASTER_UNIT_NAME"_s,
1962 new QgsVectorFileWriter::StringOption(
1964 "Override the master unit name from the seed file with "
1965 "the provided one or two character unit name."
1971 datasetOptions.insert(
1973 new QgsVectorFileWriter::StringOption(
1975 "Override the sub unit name from the seed file with the provided "
1976 "one or two character unit name."
1982 datasetOptions.insert(
1983 u
"SUB_UNITS_PER_MASTER_UNIT"_s,
1984 new QgsVectorFileWriter::IntOption(
1986 "Override the number of subunits per master unit. "
1987 "By default the seed file value is used."
1993 datasetOptions.insert(
1994 u
"UOR_PER_SUB_UNIT"_s,
1995 new QgsVectorFileWriter::IntOption(
1997 "Override the number of UORs (Units of Resolution) "
1998 "per sub unit. By default the seed file value is used."
2004 datasetOptions.insert(
2006 new QgsVectorFileWriter::StringOption(
2008 "ORIGIN=x,y,z: Override the origin of the design plane. "
2009 "By default the origin from the seed file is used."
2015 driverMetadata.insert( u
"DGN"_s, QgsVectorFileWriter::MetaData( u
"Microstation DGN"_s, QObject::tr(
"Microstation DGN" ), u
"*.dgn"_s, u
"dgn"_s, datasetOptions, layerOptions ) );
2018 datasetOptions.clear();
2019 layerOptions.clear();
2021 datasetOptions.insert(
2023 new QgsVectorFileWriter::SetOption(
2024 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
2025 QStringList() << u
"APPLY"_s << u
"IGNORE"_s,
2030 datasetOptions.insert(
2031 u
"SPLIT_MULTIPOINT"_s,
2032 new QgsVectorFileWriter::BoolOption(
2034 "Should multipoint soundings be split into many single point sounding features. "
2035 "Multipoint geometries are not well handled by many formats, "
2036 "so it can be convenient to split single sounding features with many points "
2037 "into many single point features."
2043 datasetOptions.insert(
2044 u
"ADD_SOUNDG_DEPTH"_s,
2045 new QgsVectorFileWriter::BoolOption(
2047 "Should a DEPTH attribute be added on SOUNDG features and assign the depth "
2048 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
2055 datasetOptions.insert(
2056 u
"RETURN_PRIMITIVES"_s,
2057 new QgsVectorFileWriter::BoolOption(
2059 "Should all the low level geometry primitives be returned as special "
2060 "IsolatedNode, ConnectedNode, Edge and Face layers."
2066 datasetOptions.insert(
2067 u
"PRESERVE_EMPTY_NUMBERS"_s,
2068 new QgsVectorFileWriter::BoolOption(
2070 "If enabled, numeric attributes assigned an empty string as a value will "
2071 "be preserved as a special numeric value. This option should not generally "
2072 "be needed, but may be useful when translated S-57 to S-57 losslessly."
2078 datasetOptions.insert(
2080 new QgsVectorFileWriter::BoolOption(
2082 "Should LNAM and LNAM_REFS fields be attached to features capturing "
2083 "the feature to feature relationships in the FFPT group of the S-57 file."
2089 datasetOptions.insert(
2090 u
"RETURN_LINKAGES"_s,
2091 new QgsVectorFileWriter::BoolOption(
2093 "Should additional attributes relating features to their underlying "
2094 "geometric primitives be attached. These are the values of the FSPT group, "
2095 "and are primarily needed when doing S-57 to S-57 translations."
2101 datasetOptions.insert(
2102 u
"RECODE_BY_DSSI"_s,
2103 new QgsVectorFileWriter::BoolOption(
2105 "Should attribute values be recoded to UTF-8 from the character encoding "
2106 "specified in the S57 DSSI record."
2114 driverMetadata.insert( u
"S57"_s, QgsVectorFileWriter::MetaData( u
"S-57 Base file"_s, QObject::tr(
"S-57 Base file" ), u
"*.000"_s, u
"000"_s, datasetOptions, layerOptions ) );
2117 datasetOptions.clear();
2118 layerOptions.clear();
2121 .insert( u
"SDTS"_s, QgsVectorFileWriter::MetaData( u
"Spatial Data Transfer Standard [SDTS]"_s, QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ), u
"*catd.ddf"_s, u
"ddf"_s, datasetOptions, layerOptions ) );
2124 datasetOptions.clear();
2125 layerOptions.clear();
2127 datasetOptions.insert(
2129 new QgsVectorFileWriter::BoolOption(
2131 "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2132 "tables in a new database. By default these metadata tables are created "
2133 "when a new database is created."
2140 datasetOptions.insert( u
"SPATIALITE"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2143 datasetOptions.insert( u
"INIT_WITH_EPSG"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2145 layerOptions.insert(
2147 new QgsVectorFileWriter::SetOption(
2149 "Controls the format used for the geometry column. Defaults to WKB. "
2150 "This is generally more space and processing efficient, but harder "
2151 "to inspect or use in simple applications than WKT (Well Known Text)."
2153 QStringList() << u
"WKB"_s << u
"WKT"_s,
2158 layerOptions.insert(
2160 new QgsVectorFileWriter::BoolOption(
2162 "Controls whether layer and field names will be laundered for easier use "
2163 "in SQLite. Laundered names will be converted to lower case and some special "
2164 "characters(' - #) will be changed to underscores."
2170 layerOptions.insert( u
"SPATIAL_INDEX"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2172 layerOptions.insert( u
"COMPRESS_GEOM"_s,
new QgsVectorFileWriter::HiddenOption( u
"NO"_s ) );
2174 layerOptions.insert( u
"SRID"_s,
new QgsVectorFileWriter::HiddenOption( QString() ) );
2176 layerOptions.insert(
2177 u
"COMPRESS_COLUMNS"_s,
2178 new QgsVectorFileWriter::StringOption(
2180 "column_name1[,column_name2, …] A list of (String) columns that "
2181 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2182 "for databases that have big string blobs. However, use with care, since "
2183 "the value of such columns will be seen as compressed binary content with "
2184 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2185 "modifying or querying compressed columns, compression/decompression is "
2186 "done transparently. However, such columns cannot be (easily) queried with "
2187 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2188 "have the 'VARCHAR_deflate' declaration type."
2194 driverMetadata.insert( u
"SQLite"_s, QgsVectorFileWriter::MetaData( u
"SQLite"_s, QObject::tr(
"SQLite" ), u
"*.sqlite"_s, u
"sqlite"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2197 datasetOptions.clear();
2198 layerOptions.clear();
2200 datasetOptions.insert(
2202 new QgsVectorFileWriter::BoolOption(
2204 "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2205 "tables in a new database. By default these metadata tables are created "
2206 "when a new database is created."
2212 datasetOptions.insert( u
"SPATIALITE"_s,
new QgsVectorFileWriter::HiddenOption( u
"YES"_s ) );
2214 datasetOptions.insert(
2215 u
"INIT_WITH_EPSG"_s,
2216 new QgsVectorFileWriter::BoolOption(
2218 "Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2219 "Set to NO for regular SQLite databases."
2225 layerOptions.insert( u
"FORMAT"_s,
new QgsVectorFileWriter::HiddenOption( u
"SPATIALITE"_s ) );
2227 layerOptions.insert(
2229 new QgsVectorFileWriter::BoolOption(
2231 "Controls whether layer and field names will be laundered for easier use "
2232 "in SQLite. Laundered names will be converted to lower case and some special "
2233 "characters(' - #) will be changed to underscores."
2239 layerOptions.insert(
2241 new QgsVectorFileWriter::BoolOption(
2243 "If the database is of the SpatiaLite flavor, and if OGR is linked "
2244 "against libspatialite, this option can be used to control if a spatial "
2245 "index must be created."
2251 layerOptions.insert(
2253 new QgsVectorFileWriter::BoolOption(
2255 "If the format of the geometry BLOB is of the SpatiaLite flavor, "
2256 "this option can be used to control if the compressed format for "
2257 "geometries (LINESTRINGs, POLYGONs) must be used."
2263 layerOptions.insert(
2265 new QgsVectorFileWriter::StringOption(
2267 "Used to force the SRID number of the SRS associated with the layer. "
2268 "When this option isn't specified and that a SRS is associated with the "
2269 "layer, a search is made in the spatial_ref_sys to find a match for the "
2270 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2271 "the spatial_ref_sys table. When the SRID option is specified, this "
2272 "search (and the eventual insertion of a new entry) will not be done: "
2273 "the specified SRID is used as such."
2279 layerOptions.insert(
2280 u
"COMPRESS_COLUMNS"_s,
2281 new QgsVectorFileWriter::StringOption(
2283 "column_name1[,column_name2, …] A list of (String) columns that "
2284 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2285 "for databases that have big string blobs. However, use with care, since "
2286 "the value of such columns will be seen as compressed binary content with "
2287 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2288 "modifying or queryings compressed columns, compression/decompression is "
2289 "done transparently. However, such columns cannot be (easily) queried with "
2290 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2291 "have the 'VARCHAR_deflate' declaration type."
2297 driverMetadata.insert( u
"SpatiaLite"_s, QgsVectorFileWriter::MetaData( u
"SpatiaLite"_s, QObject::tr(
"SpatiaLite" ), u
"*.sqlite"_s, u
"sqlite"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2299 datasetOptions.clear();
2300 layerOptions.clear();
2302 datasetOptions.insert(
2304 new QgsVectorFileWriter::StringOption(
2305 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2310 datasetOptions.insert(
2312 new QgsVectorFileWriter::StringOption(
2313 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2318#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 11, 0 )
2319 datasetOptions.insert(
2321 new QgsVectorFileWriter::SetOption(
2322 QObject::tr(
"Drawing units for the model space ($INSUNITS system variable)." ),
2323 QStringList() << u
"AUTO"_s << u
"HEADER_VALUE"_s << u
"UNITLESS"_s << u
"INCHES"_s << u
"FEET"_s << u
"MILLIMETERS"_s << u
"CENTIMETERS"_s << u
"METERS"_s << u
"US_SURVEY_FEET"_s,
2328 datasetOptions.insert(
2330 new QgsVectorFileWriter::SetOption(
2332 "Whether the current drawing uses imperial or metric hatch "
2333 "pattern and linetype ($MEASUREMENT system variable)."
2335 QStringList() << u
"HEADER_VALUE"_s << u
"IMPERIAL"_s << u
"METRIC"_s,
2341 driverMetadata.insert( u
"DXF"_s, QgsVectorFileWriter::MetaData( u
"AutoCAD DXF"_s, QObject::tr(
"AutoCAD DXF" ), u
"*.dxf"_s, u
"dxf"_s, datasetOptions, layerOptions ) );
2344 datasetOptions.clear();
2345 layerOptions.clear();
2347 datasetOptions.insert(
2349 new QgsVectorFileWriter::SetOption(
2351 "Indicates the GeoConcept export file extension. "
2352 "TXT was used by earlier releases of GeoConcept. GXT is currently used."
2354 QStringList() << u
"GXT"_s << u
"TXT"_s,
2359 datasetOptions.insert(
2361 new QgsVectorFileWriter::StringOption(
2363 "Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2364 "In this file, every line must start with //# followed by a keyword. "
2365 "Lines starting with // are comments."
2371 datasetOptions.insert(
2373 new QgsVectorFileWriter::StringOption(
2375 "Defines the feature to be created. The TYPE corresponds to one of the Name "
2376 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2377 "the Name found in the GCT file for a sub-type section within the previous "
2384 driverMetadata.insert( u
"Geoconcept"_s, QgsVectorFileWriter::MetaData( u
"Geoconcept"_s, QObject::tr(
"Geoconcept" ), u
"*.gxt *.txt"_s, u
"gxt"_s, datasetOptions, layerOptions ) );
2387 datasetOptions.clear();
2388 layerOptions.clear();
2390#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
2391 layerOptions.insert(
2392 u
"TARGET_ARCGIS_VERSION"_s,
2393 new QgsVectorFileWriter::SetOption(
2395 "Selects which ArcGIS version this dataset should be compatible with. ALL is used by default and means any ArcGIS 10.x or ArcGIS Pro version. Using ARCGIS_PRO_3_2_OR_LATER is required to "
2396 "export 64-bit integer fields as such, otherwise they will be converted as Real fields. ARCGIS_PRO_3_2_OR_LATER also supports proper Date and Time field types."
2398 QStringList() << u
"ALL"_s << u
"ARCGIS_PRO_3_2_OR_LATER"_s,
2404 layerOptions.insert(
2405 u
"FEATURE_DATASET"_s,
2406 new QgsVectorFileWriter::StringOption(
2408 "When this option is set, the new layer will be created inside the named "
2409 "FeatureDataset folder. If the folder does not already exist, it will be created."
2415 layerOptions.insert(
2417 new QgsVectorFileWriter::StringOption(
2418 QObject::tr(
"Set layer name alias." ),
2423 layerOptions.insert(
2425 new QgsVectorFileWriter::StringOption(
2426 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2431 layerOptions.insert(
2432 u
"GEOMETRY_NULLABLE"_s,
2433 new QgsVectorFileWriter::BoolOption(
2434 QObject::tr(
"Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to 'YES'." ),
2439 layerOptions.insert(
2441 new QgsVectorFileWriter::StringOption(
2442 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2459 layerOptions.insert(
2461 new QgsVectorFileWriter::StringOption(
2462 QObject::tr(
"A list of strings of format field_name=fgdb_field_type (separated by comma) to force the FileGDB column type of fields to be created." ),
2467 layerOptions.insert(
2469 new QgsVectorFileWriter::StringOption(
2470 QObject::tr(
"XML documentation for the layer." ),
2474 layerOptions.insert(
2475 u
"CONFIGURATION_KEYWORD"_s,
2476 new QgsVectorFileWriter::SetOption(
2477 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2478 { u
"DEFAULTS"_s, u
"MAX_FILE_SIZE_4GB"_s, u
"MAX_FILE_SIZE_256TB"_s },
2484 layerOptions.insert(
2485 u
"CREATE_SHAPE_AREA_AND_LENGTH_FIELDS"_s,
2486 new QgsVectorFileWriter::BoolOption(
2488 " Defaults to NO (through CreateLayer() API). When this option is set, a Shape_Area and Shape_Length special fields will be created for polygonal layers (Shape_Length only for linear "
2489 "layers). These fields will automatically be populated with the feature’s area or length whenever a new feature is added to the dataset or an existing feature is amended. When using "
2490 "ogr2ogr with a source layer that has Shape_Area/Shape_Length special fields, and this option is not explicitly specified, it will be automatically set, so that the resulting "
2491 "FileGeodatabase has those fields properly tagged."
2497 driverMetadata.insert( u
"OpenFileGDB"_s, QgsVectorFileWriter::MetaData( u
"ESRI File Geodatabase"_s, QObject::tr(
"ESRI File Geodatabase" ), u
"*.gdb"_s, u
"gdb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2499#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION( 3, 11, 0 )
2501 datasetOptions.clear();
2502 layerOptions.clear();
2504 layerOptions.insert(
2505 u
"FEATURE_DATASET"_s,
2506 new QgsVectorFileWriter::StringOption(
2508 "When this option is set, the new layer will be created inside the named "
2509 "FeatureDataset folder. If the folder does not already exist, it will be created."
2515 layerOptions.insert(
2517 new QgsVectorFileWriter::StringOption(
2518 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2523 layerOptions.insert(
2525 new QgsVectorFileWriter::StringOption(
2526 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2531 driverMetadata.insert( u
"FileGDB"_s, QgsVectorFileWriter::MetaData( u
"ESRI FileGDB"_s, QObject::tr(
"ESRI FileGDB" ), u
"*.gdb"_s, u
"gdb"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2535 datasetOptions.clear();
2536 layerOptions.clear();
2538 layerOptions.insert(
2539 u
"OGR_XLSX_FIELD_TYPES"_s,
2540 new QgsVectorFileWriter::SetOption(
2542 "By default, the driver will try to detect the data type of fields. If set "
2543 "to STRING, all fields will be of String type."
2545 QStringList() << u
"AUTO"_s << u
"STRING"_s,
2551 layerOptions.insert(
2552 u
"OGR_XLSX_HEADERS"_s,
2553 new QgsVectorFileWriter::SetOption(
2555 "By default, the driver will read the first lines of each sheet to detect "
2556 "if the first line might be the name of columns. If set to FORCE, the driver "
2557 "will consider the first line as the header line. If set to "
2558 "DISABLE, it will be considered as the first feature. Otherwise "
2559 "auto-detection will occur."
2561 QStringList() << u
"FORCE"_s << u
"DISABLE"_s << u
"AUTO"_s,
2568 .insert( u
"XLSX"_s, QgsVectorFileWriter::MetaData( u
"MS Office Open XML spreadsheet"_s, QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ), u
"*.xlsx"_s, u
"xlsx"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2571 datasetOptions.clear();
2572 layerOptions.clear();
2574 layerOptions.insert(
2575 u
"OGR_ODS_FIELD_TYPES"_s,
2576 new QgsVectorFileWriter::SetOption(
2578 "By default, the driver will try to detect the data type of fields. If set "
2579 "to STRING, all fields will be of String type."
2581 QStringList() << u
"AUTO"_s << u
"STRING"_s,
2587 layerOptions.insert(
2588 u
"OGR_ODS_HEADERS"_s,
2589 new QgsVectorFileWriter::SetOption(
2591 "By default, the driver will read the first lines of each sheet to detect "
2592 "if the first line might be the name of columns. If set to FORCE, the driver "
2593 "will consider the first line as the header line. If set to "
2594 "DISABLE, it will be considered as the first feature. Otherwise "
2595 "auto-detection will occur."
2597 QStringList() << u
"FORCE"_s << u
"DISABLE"_s << u
"AUTO"_s,
2603 driverMetadata.insert( u
"ODS"_s, QgsVectorFileWriter::MetaData( u
"Open Document Spreadsheet"_s, QObject::tr(
"Open Document Spreadsheet [ODS]" ), u
"*.ods"_s, u
"ods"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2606 datasetOptions.clear();
2607 layerOptions.clear();
2609 QStringList compressionMethods;
2610 const QStringList searchCompressions = { u
"NONE"_s, u
"SNAPPY"_s, u
"BROTLI"_s, u
"ZSTD"_s };
2612 if ( GDALDriverH hParquetDrv = GDALGetDriverByName(
"PARQUET" ) )
2614 if (
const char *xml = GDALGetMetadataItem( hParquetDrv, GDAL_DS_LAYER_CREATIONOPTIONLIST,
nullptr ) )
2616 for (
const QString &comp : searchCompressions )
2618 QRegularExpression re(
"<Value[^>]*>\\s*" + comp +
"\\s*</Value>" );
2619 if ( re.match( QString::fromUtf8( xml ) ).hasMatch() )
2621 compressionMethods << comp;
2627 layerOptions.insert(
2629 new QgsVectorFileWriter::SetOption(
2630 QObject::tr(
"Compression method." ),
2637#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 12, 0 )
2638 layerOptions.insert(
2639 u
"COMPRESSION_LEVEL"_s,
2640 new QgsVectorFileWriter::IntOption(
2641 QObject::tr(
"Compression level." ),
2647#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION( 3, 9, 0 )
2648 layerOptions.insert(
2650 new QgsVectorFileWriter::BoolOption(
2651 QObject::tr(
"Whether to sort by spatial location. Enables faster spatial filtering on reading." ),
2656 layerOptions.insert(
2657 u
"WRITE_COVERING_BBOX"_s,
2658 new QgsVectorFileWriter::BoolOption(
2659 QObject::tr(
"Whether to write the bounding box of geometries into columns." ),
2665 layerOptions.insert(
2666 u
"GEOMETRY_ENCODING"_s,
2667 new QgsVectorFileWriter::SetOption(
2668 QObject::tr(
"Geometry encoding." ),
2669 QStringList() << u
"WKB"_s << u
"WKT"_s << u
"GEOARROW"_s,
2675 layerOptions.insert(
2676 u
"ROW_GROUP_SIZE"_s,
2677 new QgsVectorFileWriter::IntOption(
2678 QObject::tr(
"Maximum number of rows per group." ),
2683 layerOptions.insert(
2685 new QgsVectorFileWriter::StringOption(
2686 QObject::tr(
"Name for the feature identifier column" ),
2691 layerOptions.insert(
2693 new QgsVectorFileWriter::StringOption(
2694 QObject::tr(
"Name for the geometry column" ),
2699 layerOptions.insert(
2701 new QgsVectorFileWriter::SetOption(
2702 QObject::tr(
"Name of the coordinate system for the edges." ),
2703 QStringList() << u
"PLANAR"_s << u
"SPHERICAL"_s,
2709 driverMetadata.insert( u
"Parquet"_s, QgsVectorFileWriter::MetaData( u
"(Geo)Parquet"_s, QObject::tr(
"(Geo)Parquet" ), u
"*.parquet"_s, u
"parquet"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2712 datasetOptions.clear();
2713 layerOptions.clear();
2715 datasetOptions.insert(
2717 new QgsVectorFileWriter::SetOption(
2718 QObject::tr(
"Line termination character sequence." ),
2719 QStringList() << u
"CRLF"_s << u
"LF"_s,
2726 layerOptions.insert(
2728 new QgsVectorFileWriter::SetOption(
2729 QObject::tr(
"Format of geometry columns." ),
2730 QStringList() << u
"geometry"_s << u
"geography"_s,
2736 layerOptions.insert(
2738 new QgsVectorFileWriter::BoolOption(
2740 "Controls whether layer and field names will be laundered for easier use. "
2741 "Laundered names will be converted to lower case and some special "
2742 "characters(' - #) will be changed to underscores."
2748 layerOptions.insert(
2750 new QgsVectorFileWriter::StringOption(
2752 "Name for the geometry column. Defaults to wkb_geometry "
2753 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography"
2758 layerOptions.insert( u
"SCHEMA"_s,
new QgsVectorFileWriter::StringOption( QObject::tr(
"Name of schema into which to create the new table" ) ) );
2760 layerOptions.insert(
2762 new QgsVectorFileWriter::BoolOption(
2763 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2768 layerOptions.insert(
2770 new QgsVectorFileWriter::BoolOption(
2771 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2776 layerOptions.insert(
2778 new QgsVectorFileWriter::SetOption(
2779 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2780 QStringList() << u
"YES"_s << u
"NO"_s << u
"IF_EXISTS"_s,
2786 layerOptions.insert(
2788 new QgsVectorFileWriter::StringOption(
2790 "Used to force the SRID number of the SRS associated with the layer. "
2791 "When this option isn't specified and that a SRS is associated with the "
2792 "layer, a search is made in the spatial_ref_sys to find a match for the "
2793 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2794 "the spatial_ref_sys table. When the SRID option is specified, this "
2795 "search (and the eventual insertion of a new entry) will not be done: "
2796 "the specified SRID is used as such."
2802 layerOptions.insert(
2803 u
"POSTGIS_VERSION"_s,
2804 new QgsVectorFileWriter::StringOption(
2806 "Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2807 "Important to set it correctly if using non-linear geometry types"
2813 driverMetadata.insert( u
"PGDUMP"_s, QgsVectorFileWriter::MetaData( u
"PostgreSQL SQL dump"_s, QObject::tr(
"PostgreSQL SQL dump" ), u
"*.sql"_s, u
"sql"_s, datasetOptions, layerOptions, u
"UTF-8"_s ) );
2816 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2817 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2818 ~QgsVectorFileWriterMetadataContainer()
2820 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2822 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2823 delete optionIt.value();
2824 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2825 delete optionIt.value();
2829 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2835 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2836 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2838 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2840 if ( it.key() ==
"PGDUMP"_L1 && driverName !=
"PGDUMP"_L1 && driverName !=
"PostgreSQL SQL dump"_L1 )
2845 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2860 return QStringList();
2869 return QStringList();
2900 return mCapabilities;
2910 QgsFeatureList::iterator fIt = features.begin();
2912 for ( ; fIt != features.end(); ++fIt )
2934 mRenderContext.expressionContext().setFeature( feature );
2937 QString styleString;
2938 QString currentStyle;
2940 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2941 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2943 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2944 for (
int i = 0; i < nSymbolLayers; ++i )
2947 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2953 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2954 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2956 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2962 if ( symbolIt != symbols.constBegin() || i != 0 )
2964 styleString.append(
';' );
2966 styleString.append( currentStyle );
2971 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2972 if ( !writeFeature(
mLayer, poFeature.get() ) )
2984 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2992 if ( !writeFeature(
mLayer, poFeature.get() ) )
3016 int fldIdx = it.key();
3017 int ogrField = it.value();
3019 QVariant attrValue = feature.
attribute( fldIdx );
3024 OGR_F_UnsetField( poFeature.get(), ogrField );
3037 OGR_F_SetFieldNull( poFeature.get(), ogrField );
3058 switch ( field.
type() )
3060 case QMetaType::Type::Int:
3061 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
3063 case QMetaType::Type::LongLong:
3064 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
3066 case QMetaType::Type::Bool:
3067 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
3069 case QMetaType::Type::QString:
3070 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
3072 case QMetaType::Type::Double:
3073 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
3075 case QMetaType::Type::QDate:
3076 OGR_F_SetFieldDateTime( poFeature.get(), ogrField, attrValue.toDate().year(), attrValue.toDate().month(), attrValue.toDate().day(), 0, 0, 0, 0 );
3078 case QMetaType::Type::QDateTime:
3081 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( u
"yyyy/MM/dd hh:mm:ss.zzz"_s ) ).constData() );
3085 const QDateTime dt = attrValue.toDateTime();
3086 const QDate date = dt.date();
3087 const QTime time = dt.time();
3088 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField, date.year(), date.month(), date.day(), time.hour(), time.minute(),
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
QgsOgrUtils::OGRTZFlagFromQt( dt ) );
3091 case QMetaType::Type::QTime:
3094 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
3098 const QTime time = attrValue.toTime();
3099 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField, 0, 0, 0, time.hour(), time.minute(),
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ), 0 );
3103 case QMetaType::Type::QByteArray:
3105 const QByteArray ba = attrValue.toByteArray();
3106 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
3110 case QMetaType::Type::UnknownType:
3113 case QMetaType::Type::QStringList:
3118 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3120 if ( !doc.isNull() )
3122 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
3124 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3128 QStringList list = attrValue.toStringList();
3129 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
3131 int count = list.count();
3132 char **lst =
new char *[count + 1];
3136 for (
const QString &
string : list )
3138 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
3142 lst[count] =
nullptr;
3143 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
3148 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
3153 case QMetaType::Type::QVariantList:
3157 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3159 if ( !doc.isNull() )
3161 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
3163 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3168 if ( field.
subType() == QMetaType::Type::QString )
3170 QStringList list = attrValue.toStringList();
3171 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
3173 int count = list.count();
3174 char **lst =
new char *[count + 1];
3178 for (
const QString &
string : list )
3180 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
3184 lst[count] =
nullptr;
3185 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
3190 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
3194 else if ( field.
subType() == QMetaType::Type::Int )
3196 const QVariantList list = attrValue.toList();
3197 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
3199 const int count = list.count();
3200 int *lst =
new int[count];
3204 for (
const QVariant &value : list )
3206 lst[pos] = value.toInt();
3210 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
3215 QStringList strings;
3216 strings.reserve( list.size() );
3217 for (
const QVariant &value : list )
3219 strings << QString::number( value.toInt() );
3221 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3225 else if ( field.
subType() == QMetaType::Type::Double )
3227 const QVariantList list = attrValue.toList();
3228 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
3230 const int count = list.count();
3231 double *lst =
new double[count];
3235 for (
const QVariant &value : list )
3237 lst[pos] = value.toDouble();
3241 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3246 QStringList strings;
3247 strings.reserve( list.size() );
3248 for (
const QVariant &value : list )
3250 strings << QString::number( value.toDouble() );
3252 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3256 else if ( field.
subType() == QMetaType::Type::LongLong )
3258 const QVariantList list = attrValue.toList();
3259 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3261 const int count = list.count();
3262 long long *lst =
new long long[count];
3266 for (
const QVariant &value : list )
3268 lst[pos] = value.toLongLong();
3272 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3277 QStringList strings;
3278 strings.reserve( list.size() );
3279 for (
const QVariant &value : list )
3281 strings << QString::number( value.toLongLong() );
3283 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3290 case QMetaType::Type::QVariantMap:
3293 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3294 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3296 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3298 if ( !doc.isNull() )
3300 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3301 jsonString = QString::fromUtf8( json.data() );
3303 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3313 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" ).arg(
mFields.at( fldIdx ).name() ).arg( ogrField ).arg( attrValue.typeName(), attrValue.toString() );
3325 QgsGeometry geom = feature.
geometry();
3326 if ( mCoordinateTransform )
3331 geom.
transform( *mCoordinateTransform );
3333 catch ( QgsCsException & )
3367 QVector<QgsGeometry> geoms = geom.
coerceToType( coercedType );
3368 if ( geoms.size() == 1 )
3372 OGRGeometryH ogrGeom =
nullptr;
3405 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3412 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3432 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3455 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3456 if ( wkb.length() > std::numeric_limits<int>::max() )
3458 mErrorMessage = QObject::tr(
"Feature geometry not imported (too large geometry)" );
3461 OGR_G_DestroyGeometry( ogrGeom );
3464 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ),
static_cast<int>( wkb.length() ) );
3465 if ( err != OGRERR_NONE )
3467 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3470 OGR_G_DestroyGeometry( ogrGeom );
3475 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3489 for (
int i = 0; i < attributes.size(); i++ )
3491 if ( omap.find( i ) != omap.end() )
3496bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3498 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3500 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3510 if ( mUsingTransaction )
3512 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3514 QgsDebugError( u
"Error while committing transaction on OGRLayer."_s );
3527 const QString &fileName,
3528 const QString &fileEncoding,
3530 const QString &driverName,
3533 const QStringList &datasourceOptions,
3534 const QStringList &layerOptions,
3535 bool skipAttributeCreation,
3536 QString *newFilename,
3581 const QString &fileName,
3582 const QString &fileEncoding,
3584 const QString &driverName,
3587 const QStringList &datasourceOptions,
3588 const QStringList &layerOptions,
3589 bool skipAttributeCreation,
3590 QString *newFilename,
3632 if ( !layer || !layer->
isValid() )
3639 details.sourceCrs = layer->
crs();
3640 details.sourceWkbType = layer->
wkbType();
3641 details.sourceFields = layer->
fields();
3650 if ( details.storageType ==
"ESRI Shapefile"_L1 )
3658 details.geometryTypeScanIterator = layer->
getFeatures( req );
3665 details.shallTransform =
false;
3670 details.shallTransform =
true;
3675 details.outputCrs = details.sourceCrs;
3678 details.destWkbType = details.sourceWkbType;
3692 details.attributes.clear();
3693 else if ( details.attributes.isEmpty() )
3696 for (
int idx : allAttributes )
3698 QgsField fld = details.sourceFields.
at( idx );
3699 if ( details.providerType ==
"oracle"_L1 && fld.
typeName().contains(
"SDO_GEOMETRY"_L1 ) )
3701 details.attributes.append( idx );
3705 if ( !details.attributes.isEmpty() )
3707 for (
int attrIdx : std::as_const( details.attributes ) )
3709 if ( details.sourceFields.
exists( attrIdx ) )
3711 QgsField field = details.sourceFields.
at( attrIdx );
3713 details.outputFields.
append( field );
3717 QgsDebugError( u
"No such source field with index '%1' available."_s.arg( attrIdx ) );
3724 if ( details.providerType ==
"spatialite"_L1 )
3726 for (
int i = 0; i < details.outputFields.
size(); i++ )
3728 if ( details.outputFields.
at( i ).
type() == QMetaType::Type::LongLong )
3733 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3735 details.outputFields[i].setType( QMetaType::Type::Int );
3743 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3745 QgsFeatureRequest req;
3753 bool useFilterRect =
true;
3754 if ( details.shallTransform )
3759 QgsCoordinateTransform extentTransform = options.
ct;
3763 catch ( QgsCsException & )
3765 useFilterRect =
false;
3768 if ( useFilterRect )
3774 details.filterRectEngine->prepareGeometry();
3776 details.sourceFeatureIterator = layer->
getFeatures( req );
3787 PreparedWriterDetails &details,
const QString &fileName,
const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename, QString *
errorMessage, QString *newLayer
3794 PreparedWriterDetails &details,
3795 const QString &fileName,
3796 const QgsCoordinateTransformContext &transformContext,
3797 const QgsVectorFileWriter::SaveVectorOptions &options,
3798 QString *newFilename,
3806 int lastProgressReport = 0;
3807 long long total = details.featureCount;
3810 if ( details.providerType ==
"ogr"_L1 && !details.dataSourceUri.isEmpty() )
3812 QString srcFileName( details.providerUriParams.value( u
"path"_s ).toString() );
3813 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3816 QgsDataSourceUri uri( details.dataSourceUri );
3818 && options.
layerName != details.providerUriParams.value( u
"layerName"_s ) ) )
3821 *
errorMessage = QObject::tr(
"Cannot overwrite an OGR layer in place" );
3829 QgsFeatureIterator fit = details.geometryTypeScanIterator;
3841 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3842 if ( newProgress != lastProgressReport )
3844 lastProgressReport = newProgress;
3859 QString tempNewFilename;
3860 QString tempNewLayer;
3862 QgsVectorFileWriter::SaveVectorOptions newOptions = options;
3868 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
3872 *newFilename = tempNewFilename;
3875 *newLayer = tempNewLayer;
3904 switch ( writer->symbologyExport() )
3908 QgsFeatureRenderer *r = details.renderer.get();
3921 int n = 0, errors = 0;
3930 writer->startRender( details.renderer.get(), details.sourceFields );
3932 writer->resetMap( details.attributes );
3934 writer->mFields = details.sourceFields;
3938 int initialProgress = lastProgressReport;
3939 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3950 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3951 if ( newProgress < 100 && newProgress != lastProgressReport )
3953 lastProgressReport = newProgress;
3958 if ( details.shallTransform )
3969 catch ( QgsCsException &e )
3971 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" ).arg( fet.
id() ).arg( e.
what() );
3988 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3995 *
errorMessage = QObject::tr(
"Feature write errors:" );
4001 if ( errors > 1000 )
4005 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
4015 writer->stopRender();
4019 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
4024 bool metadataFailure =
false;
4040 metadataFailure =
true;
4043 catch ( QgsNotSupportedException &e )
4051 metadataFailure =
true;
4062 QgsVectorFileWriter::PreparedWriterDetails details;
4063 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4074 QgsVectorFileWriter::PreparedWriterDetails details;
4075 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4084 const QString &fileName,
4088 QString *newFilename,
4092 QgsVectorFileWriter::PreparedWriterDetails details;
4093 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
4102 QFileInfo fi( fileName );
4103 QDir dir = fi.dir();
4106 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
4108 filter << fi.completeBaseName() + suffix;
4112 const auto constEntryList = dir.entryList( filter );
4113 for (
const QString &file : constEntryList )
4115 QFile f( dir.canonicalPath() +
'/' + file );
4118 QgsDebugError( u
"Removing file %1 failed: %2"_s.arg( file, f.errorString() ) );
4134 QStringList driverNames;
4137 for (
int i = 0; i < GDALGetDriverCount(); ++i )
4139 GDALDriverH
driver = GDALGetDriver( i );
4146 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
4147 if ( driverExtensions.isEmpty() )
4150 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
4151 if ( splitExtensions.intersects( multiLayerExtensions ) )
4153 driverNames << GDALGetDescription(
driver );
4161 static QReadWriteLock sFilterLock;
4162 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
4166 const auto it = sFilters.constFind( options );
4167 if ( it != sFilters.constEnd() )
4171 QList< QgsVectorFileWriter::FilterFormatDetails > results;
4174 int const drvCount = OGRGetDriverCount();
4178 for (
int i = 0; i < drvCount; ++i )
4180 OGRSFDriverH drv = OGRGetDriver( i );
4183 const QString drvName = GDALGetDescription( drv );
4187 if ( !multiLayerDrivers.contains( drvName ) )
4191 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
4192 bool nonSpatialFormat =
false;
4195 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr );
4198 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4203 if ( nonSpatialFormat )
4208 if ( filterString.isEmpty() )
4215 globs = metadata.
glob.toLower().split(
' ' );
4221 details.
globs = globs;
4229 if ( options & SortRecommended )
4231 if ( a.driverName ==
"GPKG"_L1 )
4233 else if ( b.driverName ==
"GPKG"_L1 )
4235 else if ( a.driverName ==
"ESRI Shapefile"_L1 )
4237 else if ( b.driverName ==
"ESRI Shapefile"_L1 )
4244 sFilters.insert( options, results );
4251 QSet< QString > extensions;
4253 const thread_local QRegularExpression rx( u
"\\*\\.(.*)$"_s );
4257 for (
const QString &glob : format.globs )
4259 const QRegularExpressionMatch match = rx.match( glob );
4260 if ( !match.hasMatch() )
4263 const QString matched = match.captured( 1 );
4264 extensions.insert( matched );
4268 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
4270 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString &a,
const QString &b ) ->
bool {
4271 if ( options & SortRecommended )
4273 if ( a ==
"gpkg"_L1 )
4275 else if ( b ==
"gpkg"_L1 )
4277 else if ( a ==
"shp"_L1 )
4279 else if ( b ==
"shp"_L1 )
4283 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4286 return extensionList;
4291 QList< QgsVectorFileWriter::DriverDetails > results;
4294 const int drvCount = OGRGetDriverCount();
4298 QStringList writableDrivers;
4299 for (
int i = 0; i < drvCount; ++i )
4301 OGRSFDriverH drv = OGRGetDriver( i );
4304 const QString drvName = GDALGetDescription( drv );
4308 if ( !multiLayerDrivers.contains( drvName ) )
4316 if ( drvName ==
"ODS"_L1 || drvName ==
"XLSX"_L1 || drvName ==
"XLS"_L1 )
4320 if ( drvName ==
"ESRI Shapefile"_L1 )
4322 writableDrivers << u
"DBF file"_s;
4324 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4327 if ( drvName ==
"MapInfo File"_L1 )
4329 writableDrivers << u
"MapInfo MIF"_s;
4331 else if ( drvName ==
"SQLite"_L1 )
4338 QString option = u
"SPATIALITE=YES"_s;
4339 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4340 OGRSFDriverH poDriver;
4342 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4348 writableDrivers << u
"SpatiaLite"_s;
4349 OGR_Dr_DeleteDataSource( poDriver, u
"/vsimem/spatialitetest.sqlite"_s.toUtf8().constData() );
4352 CPLFree( options[0] );
4354 writableDrivers << drvName;
4359 results.reserve( writableDrivers.count() );
4360 for (
const QString &drvName : std::as_const( writableDrivers ) )
4373 if ( options & SortRecommended )
4375 if ( a.driverName ==
"GPKG"_L1 )
4377 else if ( b.driverName ==
"GPKG"_L1 )
4379 else if ( a.driverName ==
"ESRI Shapefile"_L1 )
4381 else if ( b.driverName ==
"ESRI Shapefile"_L1 )
4385 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4392 QString ext = extension.trimmed();
4393 if ( ext.isEmpty() )
4396 if ( ext.startsWith(
'.' ) )
4400 int const drvCount = GDALGetDriverCount();
4402 for (
int i = 0; i < drvCount; ++i )
4404 GDALDriverH drv = GDALGetDriver( i );
4410 QString drvName = GDALGetDriverShortName( drv );
4411 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4413 const auto constDriverExtensions = driverExtensions;
4414 for (
const QString &
driver : constDriverExtensions )
4416 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4427 QString filterString;
4431 if ( !filterString.isEmpty() )
4432 filterString +=
";;"_L1;
4434 filterString += details.filterString;
4436 return filterString;
4445 return u
"%1 (%2 %3)"_s.arg( metadata.
trLongName, metadata.
glob.toLower(), metadata.
glob.toUpper() );
4450 if ( codecName ==
"System"_L1 )
4453 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4454 const QRegularExpressionMatch match = re.match( codecName );
4455 if ( match.hasMatch() )
4457 QString
c = match.captured( 2 ).remove(
'-' );
4459 ( void )
c.toInt( &isNumber );
4473 QgsFeatureRenderer *renderer = vl->
renderer();
4487 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4488 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4491 int nTotalLevels = 0;
4493 QgsSymbolList::iterator symbolIt = symbolList.begin();
4494 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4496 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4497 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4499 int nLevels = ( *symbolIt )->symbolLayerCount();
4500 for (
int i = 0; i < nLevels; ++i )
4502 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4503 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(), ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4507 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4512 if ( !details.renderer )
4515 mRenderContext.expressionContext() = details.expressionContext;
4517 QHash< QgsSymbol *, QList<QgsFeature> > features;
4526 startRender( details.renderer.get(), details.sourceFields );
4530 QgsSymbol *featureSymbol =
nullptr;
4544 catch ( QgsCsException &e )
4546 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" ).arg( e.
what() );
4554 mRenderContext.expressionContext().setFeature( fet );
4556 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4557 if ( !featureSymbol )
4562 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4563 if ( it == features.end() )
4565 it = features.insert( featureSymbol, QList<QgsFeature>() );
4567 it.value().append( fet );
4572 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4573 for (
int i = 0; i < symbols.count(); i++ )
4575 QgsSymbol *sym = symbols[i];
4579 if ( level < 0 || level >= 1000 )
4581 QgsSymbolLevelItem item( sym, j );
4582 while ( level >= levels.count() )
4584 levels[level].append( item );
4589 int nTotalFeatures = 0;
4592 for (
int l = 0; l < levels.count(); l++ )
4595 for (
int i = 0; i < level.count(); i++ )
4597 QgsSymbolLevelItem &item = level[i];
4598 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4599 if ( levelIt == features.end() )
4605 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4606 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4608 int llayer = item.
layer();
4609 QList<QgsFeature> &featureList = levelIt.value();
4610 QList<QgsFeature>::iterator featureIt = featureList.begin();
4611 for ( ; featureIt != featureList.end(); ++featureIt )
4621 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4622 if ( !styleString.isEmpty() )
4624 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4625 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4638 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4655 return 1000 / scale;
4671 return scale / 1000;
4677void QgsVectorFileWriter::startRender( QgsFeatureRenderer *sourceRenderer,
const QgsFields &fields )
4679 mRenderer = createSymbologyRenderer( sourceRenderer );
4685 mRenderer->startRender( mRenderContext, fields );
4688void QgsVectorFileWriter::stopRender()
4695 mRenderer->stopRender( mRenderContext );
4698std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer( QgsFeatureRenderer *sourceRenderer )
const
4711 if ( !sourceRenderer )
4716 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4719void QgsVectorFileWriter::addRendererAttributes( QgsFeatureRenderer *renderer, QgsRenderContext &context,
const QgsFields &fields,
QgsAttributeList &attList )
4723 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4724 for (
const QString &attr : rendererAttributes )
4729 attList.append( index );
4735QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4738 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4740 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4742 QgsVectorFileWriter::Option *option = it.value();
4743 switch ( option->
type )
4747 QgsVectorFileWriter::IntOption *opt =
dynamic_cast<QgsVectorFileWriter::IntOption *
>( option );
4750 list.append( u
"%1=%2"_s.arg( it.key() ).arg( opt->
defaultValue ) );
4757 QgsVectorFileWriter::SetOption *opt =
dynamic_cast<QgsVectorFileWriter::SetOption *
>( option );
4760 list.append( u
"%1=%2"_s.arg( it.key(), opt->
defaultValue ) );
4767 QgsVectorFileWriter::StringOption *opt =
dynamic_cast<QgsVectorFileWriter::StringOption *
>( option );
4770 list.append( u
"%1=%2"_s.arg( it.key(), opt->
defaultValue ) );
4776 QgsVectorFileWriter::HiddenOption *opt =
dynamic_cast<QgsVectorFileWriter::HiddenOption *
>( option );
4777 if ( opt && !opt->
mValue.isEmpty() )
4779 list.append( u
"%1=%2"_s.arg( it.key(), opt->
mValue ) );
4790 OGRSFDriverH hDriver =
nullptr;
4794 const QString drvName = GDALGetDescription( hDriver );
4796 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4801 if ( !( drvName ==
"ESRI Shapefile"_L1 && QFile::exists( datasetName ) ) )
4804 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4808 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4811 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4814 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4817 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4829 OGRSFDriverH hDriver =
nullptr;
4834 QString layerName( layerNameIn );
4835 if ( layerName.isEmpty() )
4836 layerName = QFileInfo( datasetName ).baseName();
4838 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4844 OGRSFDriverH hDriver =
nullptr;
4848 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4854 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4855 const auto constAttributes = attributes;
4856 for (
int idx : constAttributes )
4859 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ FieldComments
Writer can support field comments.
@ FieldAliases
Writer can support field aliases.
DistanceUnit
Units of distance.
QFlags< VectorFileWriterCapability > VectorFileWriterCapabilities
Capabilities supported by a QgsVectorFileWriter object.
RenderUnit
Rendering size units.
@ Millimeters
Millimeters.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ LineStringM
LineStringM.
@ NurbsCurveM
NurbsCurveM.
@ MultiPolygon25D
MultiPolygon25D.
@ LineStringZM
LineStringZM.
@ MultiLineString
MultiLineString.
@ NurbsCurveZ
NurbsCurveZ.
@ NurbsCurveZM
NurbsCurveZM.
@ MultiPolygonZ
MultiPolygonZ.
@ LineStringZ
LineStringZ.
FeatureSymbologyExport
Options for exporting features considering their symbology.
@ PerFeature
Keeps the number of features and export symbology per feature.
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels).
@ NoSymbology
Export only data.
@ Reverse
Reverse/inverse transform (from destination to source).
Provides common functionality for database based connections.
virtual QgsFieldDomain * fieldDomain(const QString &name) const
Returns the field domain with the specified name from the provider.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QFlags< WkbFlag > WkbFlags
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Abstract base class for all 2D vector feature renderers.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature()).
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QFlags< SinkFlag > SinkFlags
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
QString domainName() const
Returns the associated field domain name, for providers which support field domains.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
void setName(const QString &name)
Set the field name.
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
QgsFieldConstraints constraints
Container of fields for a vector layer.
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Q_INVOKABLE bool exists(int i) const
Returns if a field index is valid.
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.).
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Sets the current locale to the c locale for the lifetime of the object.
static void warning(const QString &msg)
Goes to qWarning.
static QgsAbstractDatabaseProviderConnection * databaseConnection(const QgsMapLayer *layer)
Creates and returns the (possibly nullptr) database connection for a layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static OGRwkbGeometryType qgsWkbTypeToOgrGeometryType(Qgis::WkbType wkbType, bool approx=false)
Converts a QgsWkbTypes::Type to a OGRwkbGeometryType.
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
A convenience class that simplifies locking and unlocking QReadWriteLocks.
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
An available option for configuring file writing for a particular output format, presenting an boolea...
Interface to convert raw field values to their user-friendly values.
FieldValueConverter()=default
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
An available option for configuring file writing for a particular output format, presenting an intege...
QgsVectorFileWriter::OptionType type
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multipart geometries.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QStringList attributesExportNames
Attributes export names.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
bool includeConstraints
Set to true to transfer field constraints to the exported vector file.
const QgsAbstractDatabaseProviderConnection * sourceDatabaseProviderConnection
Source database provider connection, for field domains.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
Qgis::FeatureSymbologyExport symbologyExport
Symbology to export.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set).
bool onlySelectedFeatures
Write only selected features of layer.
QgsVectorFileWriter::FieldNameSource fieldNameSource
Source for exported field names.
bool skipAttributeCreation
Only write geometries.
bool setFieldDomains
Set to true to transfer field domains to the exported vector file.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
An available option for configuring file writing for a particular output format, presenting a choice ...
An available option for configuring file writing for a particular output format, presenting a freefor...
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
Qgis::FeatureSymbologyExport mSymbologyExport
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
Qgis::WkbType mWkbType
Geometry type which is being used.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units).
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
OGRGeometryH createEmptyGeometry(Qgis::WkbType wkbType)
QString mOgrDriverLongName
QFlags< EditionCapability > EditionCapabilities
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
Qgis::VectorFileWriterCapabilities capabilities() const
Returns the capabilities supported by the writer.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
QString driver() const
Returns the GDAL (short) driver name associated with the output file.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind).
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
QMap< int, int > mAttrIdxToProviderIdx
Map attribute indices to OGR provider field indexes such as they are after the OGR provider has been ...
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, Qgis::WkbType overrideGeometryType=Qgis::WkbType::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.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
@ SupportsMultipleLayers
Filter to only formats which support multiple layers.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries).
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
QString driverLongName() const
Returns the GDAL long driver name associated with the output file.
QFlags< VectorFormatOption > VectorFormatOptions
WriterError mError
Contains error value if construction was not successful.
Qgis::FeatureSymbologyExport symbologyExport() const
Returns the feature symbology export handling for the writer.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
bool mIncludeConstraints
Whether to transfer field constraints to output.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
bool mSetFieldDomains
Whether to set field domains to output.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
QString errorMessage() const
Retrieves error message.
void setSymbologyScale(double scale)
Set reference scale for output.
QMap< int, int > mAttrIdxToOgrLayerIdx
Map attribute indices to OGR layer field indexes such as they are on the current mLayer instance.
static OGRwkbGeometryType ogrTypeFromWkbType(Qgis::WkbType type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Enumeration to describe how to handle existing files.
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based dataset.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE Qgis::WkbType wkbType() const final
Returns the WKBType or WKBUnknown in case of error.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const final
Queries the layer for features specified in request.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsVectorDataProvider * dataProvider() final
Returns the layer's data provider, it may be nullptr.
static Q_INVOKABLE QString translatedDisplayString(Qgis::WkbType type)
Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry...
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
static Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
QStringList multiLayerFormats()
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.