47#include <QRegularExpression>
48#include <QJsonDocument>
54#include <ogr_srs_api.h>
57#include <cpl_string.h>
76 const QString &fileEncoding,
80 const QString &driverName,
81 const QStringList &datasourceOptions,
82 const QStringList &layerOptions,
94 init( vectorFileName, fileEncoding, fields, geometryType,
95 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
100 const QString &fileEncoding,
104 const QString &driverName,
105 const QStringList &datasourceOptions,
106 const QStringList &layerOptions,
107 QString *newFilename,
110 const QString &layerName,
116 bool includeConstraints,
117 bool setFieldDomains,
120 , mWkbType( geometryType )
121 , mSymbologyExport( symbologyExport )
122 , mSymbologyScale( 1.0 )
123 , mIncludeConstraints( includeConstraints )
124 , mSetFieldDomains( setFieldDomains )
126 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
127 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
128 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource, sourceDatabaseProviderConnection );
132 const QString &fileName,
139 QString *newFilename,
153 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
157 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
165#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
166 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
168 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
172void QgsVectorFileWriter::init( QString vectorFileName,
173 QString fileEncoding,
177 const QString &driverName,
178 QStringList datasourceOptions,
179 QStringList layerOptions,
180 QString *newFilename,
181 FieldValueConverter *fieldValueConverter,
182 const QString &layerNameIn,
183 ActionOnExistingFile action,
184 QString *newLayer, SinkFlags sinkFlags,
188#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,5,0)
189 ( void )sourceDatabaseProviderConnection;
194 if ( vectorFileName.isEmpty() )
201 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
205 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
208 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
210 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
213 else if ( driverName == QLatin1String(
"DBF file" ) )
216 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
218 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
227#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
228 QString fidFieldName;
231 for (
const QString &layerOption : layerOptions )
233 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
235 fidFieldName = layerOption.mid( 4 );
239 if ( fidFieldName.isEmpty() )
240 fidFieldName = QStringLiteral(
"fid" );
245 OGRSFDriverH poDriver;
248 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
252 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
254 QString::fromUtf8( CPLGetLastErrorMsg() ) );
259 mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME,
nullptr ) );
266 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
271 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
273 vectorFileName += QLatin1String(
".shp" );
275 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
277 vectorFileName += QLatin1String(
".dbf" );
287 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
289 const auto constAllExts = allExts;
290 for (
const QString &ext : constAllExts )
292 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
301 vectorFileName +=
'.' + allExts[0];
307 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
309 QDir dir( vectorFileName );
312 QFileInfoList fileList = dir.entryInfoList(
313 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
314 const auto constFileList = fileList;
315 for (
const QFileInfo &info : constFileList )
317 QFile::remove( info.absoluteFilePath() );
320 QDir().rmdir( vectorFileName );
324 QFile::remove( vectorFileName );
329 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
331 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
333 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
334 fileEncoding = metadata.compulsoryEncoding;
339 char **options =
nullptr;
340 if ( !datasourceOptions.isEmpty() )
342 options =
new char *[ datasourceOptions.size() + 1 ];
343 for (
int i = 0; i < datasourceOptions.size(); i++ )
345 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
346 options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
348 options[ datasourceOptions.size()] =
nullptr;
355 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
357 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
361 for (
int i = 0; i < datasourceOptions.size(); i++ )
362 CPLFree( options[i] );
371 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
372 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
375 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
379 QString layerName( layerNameIn );
380 if ( layerName.isEmpty() )
381 layerName = QFileInfo( vectorFileName ).baseName();
385 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
386 for (
int i = 0; i < layer_count; i++ )
388 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
389 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
391 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
394 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
395 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
409 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
413 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
416 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
419 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
420 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
424 mCodec = QTextCodec::codecForLocale();
430 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
432 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
447 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
448 if ( optIndex != -1 )
450 layerOptions.removeAt( optIndex );
453 if ( !layerOptions.isEmpty() )
455 options =
new char *[ layerOptions.size() + 1 ];
456 for (
int i = 0; i < layerOptions.size(); i++ )
459 options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
461 options[ layerOptions.size()] =
nullptr;
465 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
469 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
472 *newLayer = OGR_L_GetName(
mLayer );
473 if ( driverName == QLatin1String(
"GPX" ) )
480 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
481 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
483 *newLayer = QStringLiteral(
"waypoints" );
490 const char *pszForceGPXTrack
491 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
492 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
493 *newLayer = QStringLiteral(
"tracks" );
495 *newLayer = QStringLiteral(
"routes" );
502 const char *pszForceGPXRoute
503 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
504 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
505 *newLayer = QStringLiteral(
"routes" );
507 *newLayer = QStringLiteral(
"tracks" );
517 else if ( driverName == QLatin1String(
"DGN" ) )
519 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
523 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
528 for (
int i = 0; i < layerOptions.size(); i++ )
529 CPLFree( options[i] );
538 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
539 QFile prjFile( layerName +
".qpj" );
540 if ( prjFile.exists() )
548 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
549 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
551 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
552 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
557 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
566 QSet<int> existingIdxs;
570#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
571 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
573 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
574 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
578 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
582 CSLDestroy( papszTokens );
592#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
593 QSet<QString> existingDestDomainNames;
594 if ( sourceDatabaseProviderConnection )
596 char **domainNames = GDALDatasetGetFieldDomainNames(
mDS.get(),
nullptr );
597 for (
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
599 existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
601 CSLDestroy( domainNames );
604#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
605 QSet< QString > usedAlternativeNames;
608 const QString ogrFidColumnName { OGR_L_GetFIDColumn(
mLayer ) };
609 const int fidNameIndex = OGR_FD_GetFieldIndex( defn, ogrFidColumnName.toUtf8() );
612 const bool promoteFidColumnToAttribute = !ogrFidColumnName.isEmpty() && fidNameIndex < 0 && fields.
lookupField( ogrFidColumnName ) >= 0;
613 int offsetRoomForFid = promoteFidColumnToAttribute ? 1 : 0;
615 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
619 if ( fieldValueConverter )
621 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
626 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
635 switch ( fieldNameSource )
638 name = attrField.
name();
642 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
646 OGRFieldType ogrType = OFTString;
647 OGRFieldSubType ogrSubType = OFSTNone;
648 int ogrWidth = attrField.
length();
649 int ogrPrecision = attrField.
precision();
650 if ( ogrPrecision > 0 )
653 switch ( attrField.
type() )
655 case QMetaType::Type::LongLong:
657 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
658 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
659 ogrType = OFTInteger64;
662 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
666 case QMetaType::Type::QString:
668 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
672 case QMetaType::Type::Int:
673 ogrType = OFTInteger;
674 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
678 case QMetaType::Type::Bool:
679 ogrType = OFTInteger;
680 ogrSubType = OFSTBoolean;
685 case QMetaType::Type::Double:
686#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
687 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
690 ogrType = OFTInteger64;
697 case QMetaType::Type::QDate:
701 case QMetaType::Type::QTime:
713 case QMetaType::Type::QDateTime:
721 ogrType = OFTDateTime;
725 case QMetaType::Type::QByteArray:
729 case QMetaType::Type::QStringList:
735 ogrSubType = OFSTJSON;
739 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
740 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
742 ogrType = OFTStringList;
743 mSupportedListSubTypes.insert( QMetaType::Type::QString );
753 case QMetaType::Type::QVariantMap:
756 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
757 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
760 ogrSubType = OFSTJSON;
768 case QMetaType::Type::QVariantList:
773 ogrSubType = OFSTJSON;
778 if ( attrField.
subType() == QMetaType::Type::QString )
780 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
781 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
783 ogrType = OFTStringList;
784 mSupportedListSubTypes.insert( QMetaType::Type::QString );
793 else if ( attrField.
subType() == QMetaType::Type::Int )
795 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
796 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
798 ogrType = OFTIntegerList;
799 mSupportedListSubTypes.insert( QMetaType::Type::Int );
808 else if ( attrField.
subType() == QMetaType::Type::Double )
810 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
811 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
813 ogrType = OFTRealList;
814 mSupportedListSubTypes.insert( QMetaType::Type::Double );
823 else if ( attrField.
subType() == QMetaType::Type::LongLong )
825 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
826 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
828 ogrType = OFTInteger64List;
829 mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
843 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
844 .arg( attrField.
name() );
849 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
852 for ( i = 0; i < 10; i++ )
854 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
857 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
860 if ( j == fields.
size() )
866 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
871 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
878 OGR_Fld_SetWidth( fld.get(), ogrWidth );
881 if ( ogrPrecision >= 0 )
883 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
886 if ( ogrSubType != OFSTNone )
887 OGR_Fld_SetSubType( fld.get(), ogrSubType );
889#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
890 if ( !attrField.
alias().isEmpty() )
892 QString alternativeName = attrField.
alias();
894 while ( usedAlternativeNames.contains( alternativeName ) )
897 alternativeName = attrField.
alias() + QStringLiteral(
" (%1)" ).arg( ++counter );
899 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( alternativeName ).constData() );
900 usedAlternativeNames.insert( alternativeName );
903#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
904 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
911 OGR_Fld_SetNullable( fld.get(),
false );
915 OGR_Fld_SetUnique( fld.get(),
true );
918#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
922 if ( !domainName.isEmpty() )
924 bool canSetFieldDomainName =
false;
925 if ( existingDestDomainNames.contains( domainName ) )
929 canSetFieldDomainName =
true;
931 else if ( GDALDatasetTestCapability(
mDS.get(), ODsCAddFieldDomain ) )
941 std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
947 char *pszFailureReason =
nullptr;
948 if ( GDALDatasetAddFieldDomain(
mDS.get(), hFieldDomain, &pszFailureReason ) )
950 existingDestDomainNames.insert( domainName );
951 canSetFieldDomainName =
true;
955 QgsDebugError( QStringLiteral(
"cannot create field domain: %1" ).arg( pszFailureReason ) );
957 CPLFree( pszFailureReason );
958 OGR_FldDomain_Destroy( hFieldDomain );
964 QgsDebugError( QStringLiteral(
"Cannot retrieve field domain: %1" ).arg( domainName ) );
967 if ( canSetFieldDomainName )
969 OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
977 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
978 " width " + QString::number( ogrWidth ) +
979 " precision " + QString::number( ogrPrecision ), 2 );
980 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
983 mErrorMessage = QObject::tr(
"Creation of field %1 (%2) failed (OGR error: %3)" )
984 .arg( attrField.
name(),
985 QVariant::typeToName( attrField.
type() ),
986 QString::fromUtf8( CPLGetLastErrorMsg() ) );
991 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
992 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
993 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
996 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
1001 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
1002 .arg( attrField.
name(),
1003 QString::fromUtf8( CPLGetLastErrorMsg() ) );
1009 if ( promoteFidColumnToAttribute )
1011 if ( ogrFidColumnName.compare( attrField.
name(), Qt::CaseInsensitive ) == 0 )
1014 offsetRoomForFid = 0;
1019 ogrIdx += offsetRoomForFid;
1023 existingIdxs.insert( ogrIdx );
1031 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
1034 QString name( attrField.
name() );
1035 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1047 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
1058 *newFilename = vectorFileName;
1061 mUsingTransaction =
true;
1062 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
1064 mUsingTransaction =
false;
1074class QgsVectorFileWriterMetadataContainer
1078 QgsVectorFileWriterMetadataContainer()
1080 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
1081 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
1084 datasetOptions.clear();
1085 layerOptions.clear();
1088 QObject::tr(
"Compression method." ),
1090 << QStringLiteral(
"UNCOMPRESSED" )
1091 << QStringLiteral(
"ZSTD" )
1092 << QStringLiteral(
"LZ4" ),
1093 QStringLiteral(
"LZ4" ),
1098 QObject::tr(
"Geometry encoding." ),
1100 << QStringLiteral(
"GEOARROW" )
1101 << QStringLiteral(
"WKB" )
1102 << QStringLiteral(
"WKT" ),
1103 QStringLiteral(
"GEOARROW" ),
1108 QObject::tr(
"Maximum number of rows per batch." ),
1113 QObject::tr(
"Name for the feature identifier column" ),
1118 QObject::tr(
"Name for the geometry column" ),
1119 QStringLiteral(
"geometry" )
1122 driverMetadata.insert( QStringLiteral(
"Arrow" ),
1124 QStringLiteral(
"(Geo)Arrow" ),
1125 QObject::tr(
"(Geo)Arrow" ),
1126 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
1127 QStringLiteral(
"arrow" ),
1130 QStringLiteral(
"UTF-8" )
1135 datasetOptions.clear();
1136 layerOptions.clear();
1138 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
1140 QStringLiteral(
"Arc/Info ASCII Coverage" ),
1141 QObject::tr(
"Arc/Info ASCII Coverage" ),
1142 QStringLiteral(
"*.e00" ),
1143 QStringLiteral(
"e00" ),
1150 datasetOptions.clear();
1151 layerOptions.clear();
1154 QObject::tr(
"By default when creating new .csv files they "
1155 "are created with the line termination conventions "
1156 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1157 "This may be overridden through the use of the LINEFORMAT option." ),
1159 << QStringLiteral(
"CRLF" )
1160 << QStringLiteral(
"LF" ),
1166 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1167 "It is possible to export the geometry in its WKT representation by "
1168 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1169 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1170 "or GEOMETRY=AS_YX." ),
1172 << QStringLiteral(
"AS_WKT" )
1173 << QStringLiteral(
"AS_XYZ" )
1174 << QStringLiteral(
"AS_XY" )
1175 << QStringLiteral(
"AS_YX" ),
1181 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1182 "column of the layer and its optional width and precision." ),
1187 QObject::tr(
"Field separator character." ),
1189 << QStringLiteral(
"COMMA" )
1190 << QStringLiteral(
"SEMICOLON" )
1191 << QStringLiteral(
"TAB" ),
1192 QStringLiteral(
"COMMA" )
1196 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1198 << QStringLiteral(
"IF_NEEDED" )
1199 << QStringLiteral(
"IF_AMBIGUOUS" )
1200 << QStringLiteral(
"ALWAYS" ),
1201 QStringLiteral(
"IF_AMBIGUOUS" )
1205 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1209 driverMetadata.insert( QStringLiteral(
"CSV" ),
1211 QStringLiteral(
"Comma Separated Value [CSV]" ),
1212 QObject::tr(
"Comma Separated Value [CSV]" ),
1213 QStringLiteral(
"*.csv" ),
1214 QStringLiteral(
"csv" ),
1221 datasetOptions.clear();
1222 layerOptions.clear();
1224 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1226 QStringLiteral(
"FlatGeobuf" ),
1227 QObject::tr(
"FlatGeobuf" ),
1228 QStringLiteral(
"*.fgb" ),
1229 QStringLiteral(
"fgb" ),
1232 QStringLiteral(
"UTF-8" )
1237 datasetOptions.clear();
1238 layerOptions.clear();
1241 QObject::tr(
"Override the type of shapefile created. "
1242 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1243 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1244 "MULTIPOINTZ for 3D;" ) +
1245 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1246 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1248 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1251 << QStringLiteral(
"NULL" )
1252 << QStringLiteral(
"POINT" )
1253 << QStringLiteral(
"ARC" )
1254 << QStringLiteral(
"POLYGON" )
1255 << QStringLiteral(
"MULTIPOINT" )
1256 << QStringLiteral(
"POINTZ" )
1257 << QStringLiteral(
"ARCZ" )
1258 << QStringLiteral(
"POLYGONZ" )
1259 << QStringLiteral(
"MULTIPOINTZ" )
1260 << QStringLiteral(
"POINTM" )
1261 << QStringLiteral(
"ARCM" )
1262 << QStringLiteral(
"POLYGONM" )
1263 << QStringLiteral(
"MULTIPOINTM" )
1264 << QStringLiteral(
"POINTZM" )
1265 << QStringLiteral(
"ARCZM" )
1266 << QStringLiteral(
"POLYGONZM" )
1267 << QStringLiteral(
"MULTIPOINTZM" )
1268 << QStringLiteral(
"MULTIPATCH" )
1278 QObject::tr(
"Set the encoding value in the DBF file. "
1279 "The default value is LDID/87. It is not clear "
1280 "what other values may be appropriate." ),
1288 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1292 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1294 QStringLiteral(
"ESRI Shapefile" ),
1295 QObject::tr(
"ESRI Shapefile" ),
1296 QStringLiteral(
"*.shp" ),
1297 QStringLiteral(
"shp" ),
1304 datasetOptions.clear();
1305 layerOptions.clear();
1307 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1309 QStringLiteral(
"DBF File" ),
1310 QObject::tr(
"DBF File" ),
1311 QStringLiteral(
"*.dbf" ),
1312 QStringLiteral(
"dbf" ),
1319 datasetOptions.clear();
1320 layerOptions.clear();
1323 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1324 "of the geometries at the feature and feature collection level." ),
1329 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1330 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1335 QObject::tr(
"Whether to use RFC 7946 standard. "
1336 "If disabled GeoJSON 2008 initial version will be used. "
1337 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1341 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1343 QStringLiteral(
"GeoJSON" ),
1344 QObject::tr(
"GeoJSON" ),
1345 QStringLiteral(
"*.geojson" ),
1346 QStringLiteral(
"geojson" ),
1349 QStringLiteral(
"UTF-8" )
1354 datasetOptions.clear();
1355 layerOptions.clear();
1358 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1359 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1364 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1365 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1366 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1370 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1372 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1373 QObject::tr(
"GeoJSON - Newline Delimited" ),
1374 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1375 QStringLiteral(
"geojsonl geojsons json" ),
1378 QStringLiteral(
"UTF-8" )
1383 datasetOptions.clear();
1384 layerOptions.clear();
1387 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1388 "Default value : RSS" ),
1390 << QStringLiteral(
"RSS" )
1391 << QStringLiteral(
"ATOM" ),
1392 QStringLiteral(
"RSS" )
1396 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1397 "W3C_GEO only supports point geometries. "
1398 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1400 << QStringLiteral(
"SIMPLE" )
1401 << QStringLiteral(
"GML" )
1402 << QStringLiteral(
"W3C_GEO" ),
1403 QStringLiteral(
"SIMPLE" )
1407 QObject::tr(
"If defined to YES, extension fields will be written. "
1408 "If the field name not found in the base schema matches "
1409 "the foo_bar pattern, foo will be considered as the namespace "
1410 "of the element, and a <foo:bar> element will be written. "
1411 "Otherwise, elements will be written in the <ogr:> namespace." ),
1416 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1417 "The user will have to provide the appropriate header and footer of the document." ),
1422 QObject::tr(
"XML content that will be put between the <channel> element and the "
1423 "first <item> element for a RSS document, or between the xml tag and "
1424 "the first <entry> element for an Atom document." ),
1429 QObject::tr(
"Value put inside the <title> element in the header. "
1430 "If not provided, a dummy value will be used as that element is compulsory." ),
1435 QObject::tr(
"Value put inside the <description> element in the header. "
1436 "If not provided, a dummy value will be used as that element is compulsory." ),
1441 QObject::tr(
"Value put inside the <link> element in the header. "
1442 "If not provided, a dummy value will be used as that element is compulsory." ),
1447 QObject::tr(
"Value put inside the <updated> element in the header. "
1448 "Should be formatted as a XML datetime. "
1449 "If not provided, a dummy value will be used as that element is compulsory." ),
1454 QObject::tr(
"Value put inside the <author><name> element in the header. "
1455 "If not provided, a dummy value will be used as that element is compulsory." ),
1460 QObject::tr(
"Value put inside the <id> element in the header. "
1461 "If not provided, a dummy value will be used as that element is compulsory." ),
1465 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1467 QStringLiteral(
"GeoRSS" ),
1468 QObject::tr(
"GeoRSS" ),
1469 QStringLiteral(
"*.xml" ),
1470 QStringLiteral(
"xml" ),
1473 QStringLiteral(
"UTF-8" )
1478 datasetOptions.clear();
1479 layerOptions.clear();
1482 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1483 "Note that the schema file isn't actually accessed by OGR, so it "
1484 "is up to the user to ensure it will match the schema of the OGR "
1485 "produced GML data file." ),
1490 QObject::tr(
"This writes a GML application schema file to a corresponding "
1491 ".xsd file (with the same basename). If INTERNAL is used the "
1492 "schema is written within the GML file, but this is experimental "
1493 "and almost certainly not valid XML. "
1494 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1496 << QStringLiteral(
"EXTERNAL" )
1497 << QStringLiteral(
"INTERNAL" )
1498 << QStringLiteral(
"OFF" ),
1499 QStringLiteral(
"EXTERNAL" )
1503 QObject::tr(
"This is the prefix for the application target namespace." ),
1504 QStringLiteral(
"ogr" )
1508 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1509 "application target namespace in the GML file." ),
1514 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1515 "This is the application target namespace." ),
1516 QStringLiteral(
"http://ogr.maptools.org/" )
1520 QObject::tr(
"GML version to use." ),
1522 << QStringLiteral(
"GML2" )
1523 << QStringLiteral(
"GML3" )
1524 << QStringLiteral(
"GML3Deegree" )
1525 << QStringLiteral(
"GML3.2" ),
1526 QStringLiteral(
"GML3.2" )
1530 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1531 "If YES, SRS with EPSG authority will be written with the "
1532 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1533 "geographic SRS without explicit AXIS order, but that the same "
1534 "SRS authority code imported with ImportFromEPSGA() should be "
1535 "treated as lat/long, then the function will take care of coordinate "
1536 "order swapping. If set to NO, SRS with EPSG authority will be "
1537 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1542 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1543 "If set to NO, the <gml:boundedBy> element will not be written for "
1549 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1550 "for more readability, but at the expense of file size." ),
1555 driverMetadata.insert( QStringLiteral(
"GML" ),
1557 QStringLiteral(
"Geography Markup Language [GML]" ),
1558 QObject::tr(
"Geography Markup Language [GML]" ),
1559 QStringLiteral(
"*.gml" ),
1560 QStringLiteral(
"gml" ),
1563 QStringLiteral(
"UTF-8" )
1568 datasetOptions.clear();
1569 layerOptions.clear();
1572 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1577 QObject::tr(
"Human-readable description for the layer content" ),
1582 QObject::tr(
"Name for the feature identifier column" ),
1583 QStringLiteral(
"fid" )
1587 QObject::tr(
"Name for the geometry column" ),
1588 QStringLiteral(
"geom" )
1592 QObject::tr(
"If a spatial index must be created." ),
1596 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1598 QStringLiteral(
"GeoPackage" ),
1599 QObject::tr(
"GeoPackage" ),
1600#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
1601 QStringLiteral(
"*.gpkg *.gpkg.zip" ),
1603 QStringLiteral(
"*.gpkg" ),
1605 QStringLiteral(
"gpkg" ),
1608 QStringLiteral(
"UTF-8" )
1613 datasetOptions.clear();
1614 layerOptions.clear();
1616 driverMetadata.insert( QStringLiteral(
"GMT" ),
1618 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1619 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1620 QStringLiteral(
"*.gmt" ),
1621 QStringLiteral(
"gmt" ),
1628 datasetOptions.clear();
1629 layerOptions.clear();
1632 QObject::tr(
"By default when writing a layer whose features are of "
1633 "type wkbLineString, the GPX driver chooses to write "
1634 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1635 "they will be written as tracks." ),
1640 QObject::tr(
"By default when writing a layer whose features are of "
1641 "type wkbMultiLineString, the GPX driver chooses to write "
1642 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1643 "they will be written as routes, provided that the multilines "
1644 "are composed of only one single line." ),
1649 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1650 "extra fields will be written inside the <extensions> tag." ),
1655 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1656 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1657 QStringLiteral(
"ogr" )
1661 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1662 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1663 QStringLiteral(
"http://osgeo.org/gdal" )
1667 QObject::tr(
"By default files are created with the line termination "
1668 "conventions of the local platform (CR/LF on win32 or LF "
1669 "on all other systems). This may be overridden through use "
1670 "of the LINEFORMAT layer creation option which may have a value "
1671 "of CRLF (DOS format) or LF (Unix format)." ),
1673 << QStringLiteral(
"CRLF" )
1674 << QStringLiteral(
"LF" ),
1679 driverMetadata.insert( QStringLiteral(
"GPX" ),
1681 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1682 QObject::tr(
"GPS eXchange Format [GPX]" ),
1683 QStringLiteral(
"*.gpx" ),
1684 QStringLiteral(
"gpx" ),
1687 QStringLiteral(
"UTF-8" )
1692 datasetOptions.clear();
1693 layerOptions.clear();
1695 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1697 QStringLiteral(
"INTERLIS 1" ),
1698 QObject::tr(
"INTERLIS 1" ),
1699 QStringLiteral(
"*.itf *.xml *.ili" ),
1700 QStringLiteral(
"ili" ),
1707 datasetOptions.clear();
1708 layerOptions.clear();
1710 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1712 QStringLiteral(
"INTERLIS 2" ),
1713 QObject::tr(
"INTERLIS 2" ),
1714 QStringLiteral(
"*.xtf *.xml *.ili" ),
1715 QStringLiteral(
"ili" ),
1722 datasetOptions.clear();
1723 layerOptions.clear();
1726 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1727 QStringLiteral(
"Name" )
1731 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1732 QStringLiteral(
"Description" )
1736 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1737 "This will only affect 3D geometries and must be one of the valid KML options." ),
1739 << QStringLiteral(
"clampToGround" )
1740 << QStringLiteral(
"relativeToGround" )
1741 << QStringLiteral(
"absolute" ),
1742 QStringLiteral(
"relativeToGround" )
1746 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1747 "the id of the root <Document> node. The default value is root_doc." ),
1748 QStringLiteral(
"root_doc" )
1751 driverMetadata.insert( QStringLiteral(
"KML" ),
1753 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1754 QObject::tr(
"Keyhole Markup Language [KML]" ),
1755 QStringLiteral(
"*.kml" ),
1756 QStringLiteral(
"kml" ),
1759 QStringLiteral(
"UTF-8" )
1764 datasetOptions.clear();
1765 layerOptions.clear();
1767 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1770 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1771 "In this mode writing files can be about 5 times faster, "
1772 "but spatial queries can be up to 30 times slower." ),
1774 << QStringLiteral(
"QUICK" )
1775 << QStringLiteral(
"OPTIMIZED" ),
1776 QStringLiteral(
"QUICK" ),
1781 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1782 "to 512. MapInfo 15.2 and above creates .tab files with a "
1783 "blocksize of 16384 bytes. Any MapInfo version should be "
1784 "able to handle block sizes from 512 to 32256." ),
1788 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1789 "accuracy of the coordinates. Note: the geometry of written "
1790 "features must be within the defined box." ),
1794 insertMapInfoOptions( datasetOptions, layerOptions );
1796 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1798 QStringLiteral(
"Mapinfo" ),
1799 QObject::tr(
"Mapinfo TAB" ),
1800 QStringLiteral(
"*.tab" ),
1801 QStringLiteral(
"tab" ),
1806 datasetOptions.clear();
1807 layerOptions.clear();
1808 insertMapInfoOptions( datasetOptions, layerOptions );
1811 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1813 QStringLiteral(
"Mapinfo" ),
1814 QObject::tr(
"Mapinfo MIF" ),
1815 QStringLiteral(
"*.mif" ),
1816 QStringLiteral(
"mif" ),
1823 datasetOptions.clear();
1824 layerOptions.clear();
1827 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1828 "seed file should be used. This option is ignored if the SEED option is provided." ),
1833 QObject::tr(
"Override the seed file to use." ),
1838 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1839 "If not, only the first three elements will be copied." ),
1844 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1849 QObject::tr(
"Override the master unit name from the seed file with "
1850 "the provided one or two character unit name." ),
1855 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1856 "one or two character unit name." ),
1861 QObject::tr(
"Override the number of subunits per master unit. "
1862 "By default the seed file value is used." ),
1867 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1868 "per sub unit. By default the seed file value is used." ),
1873 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1874 "By default the origin from the seed file is used." ),
1878 driverMetadata.insert( QStringLiteral(
"DGN" ),
1880 QStringLiteral(
"Microstation DGN" ),
1881 QObject::tr(
"Microstation DGN" ),
1882 QStringLiteral(
"*.dgn" ),
1883 QStringLiteral(
"dgn" ),
1890 datasetOptions.clear();
1891 layerOptions.clear();
1894 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1896 << QStringLiteral(
"APPLY" )
1897 << QStringLiteral(
"IGNORE" ),
1898 QStringLiteral(
"APPLY" )
1902 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1903 "Multipoint geometries are not well handled by many formats, "
1904 "so it can be convenient to split single sounding features with many points "
1905 "into many single point features." ),
1910 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1911 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1917 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1918 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1923 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1924 "be preserved as a special numeric value. This option should not generally "
1925 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1930 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1931 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1936 QObject::tr(
"Should additional attributes relating features to their underlying "
1937 "geometric primitives be attached. These are the values of the FSPT group, "
1938 "and are primarily needed when doing S-57 to S-57 translations." ),
1943 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1944 "specified in the S57 DSSI record." ),
1950 driverMetadata.insert( QStringLiteral(
"S57" ),
1952 QStringLiteral(
"S-57 Base file" ),
1953 QObject::tr(
"S-57 Base file" ),
1954 QStringLiteral(
"*.000" ),
1955 QStringLiteral(
"000" ),
1962 datasetOptions.clear();
1963 layerOptions.clear();
1965 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1967 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1968 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1969 QStringLiteral(
"*catd.ddf" ),
1970 QStringLiteral(
"ddf" ),
1977 datasetOptions.clear();
1978 layerOptions.clear();
1981 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1982 "tables in a new database. By default these metadata tables are created "
1983 "when a new database is created." ),
1989 QStringLiteral(
"NO" )
1994 QStringLiteral(
"NO" )
1998 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
1999 "This is generally more space and processing efficient, but harder "
2000 "to inspect or use in simple applications than WKT (Well Known Text)." ),
2002 << QStringLiteral(
"WKB" )
2003 << QStringLiteral(
"WKT" ),
2004 QStringLiteral(
"WKB" )
2008 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2009 "in SQLite. Laundered names will be converted to lower case and some special "
2010 "characters(' - #) will be changed to underscores." ),
2015 QStringLiteral(
"NO" )
2019 QStringLiteral(
"NO" )
2027 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2028 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2029 "for databases that have big string blobs. However, use with care, since "
2030 "the value of such columns will be seen as compressed binary content with "
2031 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2032 "modifying or querying compressed columns, compression/decompression is "
2033 "done transparently. However, such columns cannot be (easily) queried with "
2034 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2035 "have the 'VARCHAR_deflate' declaration type." ),
2039 driverMetadata.insert( QStringLiteral(
"SQLite" ),
2041 QStringLiteral(
"SQLite" ),
2042 QObject::tr(
"SQLite" ),
2043 QStringLiteral(
"*.sqlite" ),
2044 QStringLiteral(
"sqlite" ),
2047 QStringLiteral(
"UTF-8" )
2052 datasetOptions.clear();
2053 layerOptions.clear();
2056 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2057 "tables in a new database. By default these metadata tables are created "
2058 "when a new database is created." ),
2063 QStringLiteral(
"YES" )
2067 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2068 "Set to NO for regular SQLite databases." ),
2073 QStringLiteral(
"SPATIALITE" )
2077 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2078 "in SQLite. Laundered names will be converted to lower case and some special "
2079 "characters(' - #) will be changed to underscores." ),
2084 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2085 "against libspatialite, this option can be used to control if a spatial "
2086 "index must be created." ),
2091 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2092 "this option can be used to control if the compressed format for "
2093 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2098 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2099 "When this option isn't specified and that a SRS is associated with the "
2100 "layer, a search is made in the spatial_ref_sys to find a match for the "
2101 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2102 "the spatial_ref_sys table. When the SRID option is specified, this "
2103 "search (and the eventual insertion of a new entry) will not be done: "
2104 "the specified SRID is used as such." ),
2109 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2110 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2111 "for databases that have big string blobs. However, use with care, since "
2112 "the value of such columns will be seen as compressed binary content with "
2113 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2114 "modifying or queryings compressed columns, compression/decompression is "
2115 "done transparently. However, such columns cannot be (easily) queried with "
2116 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2117 "have the 'VARCHAR_deflate' declaration type." ),
2121 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2123 QStringLiteral(
"SpatiaLite" ),
2124 QObject::tr(
"SpatiaLite" ),
2125 QStringLiteral(
"*.sqlite" ),
2126 QStringLiteral(
"sqlite" ),
2129 QStringLiteral(
"UTF-8" )
2133 datasetOptions.clear();
2134 layerOptions.clear();
2137 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2142 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2146 driverMetadata.insert( QStringLiteral(
"DXF" ),
2148 QStringLiteral(
"AutoCAD DXF" ),
2149 QObject::tr(
"AutoCAD DXF" ),
2150 QStringLiteral(
"*.dxf" ),
2151 QStringLiteral(
"dxf" ),
2158 datasetOptions.clear();
2159 layerOptions.clear();
2162 QObject::tr(
"Indicates the GeoConcept export file extension. "
2163 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2165 << QStringLiteral(
"GXT" )
2166 << QStringLiteral(
"TXT" ),
2167 QStringLiteral(
"GXT" )
2171 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2172 "In this file, every line must start with //# followed by a keyword. "
2173 "Lines starting with // are comments." ),
2178 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2179 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2180 "the Name found in the GCT file for a sub-type section within the previous "
2185 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2187 QStringLiteral(
"Geoconcept" ),
2188 QObject::tr(
"Geoconcept" ),
2189 QStringLiteral(
"*.gxt *.txt" ),
2190 QStringLiteral(
"gxt" ),
2197 datasetOptions.clear();
2198 layerOptions.clear();
2200#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0)
2202 QObject::tr(
"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 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." ),
2204 << QStringLiteral(
"ALL" )
2205 << QStringLiteral(
"ARCGIS_PRO_3_2_OR_LATER" ),
2206 QStringLiteral(
"ALL" )
2211 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2212 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2217 QObject::tr(
"Set layer name alias." ),
2222 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2223 QStringLiteral(
"SHAPE" )
2227 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'." ),
2232 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2233 QStringLiteral(
"OBJECTID" )
2249 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." ),
2254 QObject::tr(
"XML documentation for the layer." ),
2258 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2259 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2260 QStringLiteral(
"DEFAULTS" ),
2265 QObject::tr(
" 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 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 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 FileGeodatabase has those fields properly tagged." ),
2269 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2271 QStringLiteral(
"ESRI File Geodatabase" ),
2272 QObject::tr(
"ESRI File Geodatabase" ),
2273 QStringLiteral(
"*.gdb" ),
2274 QStringLiteral(
"gdb" ),
2277 QStringLiteral(
"UTF-8" )
2281#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,11,0)
2283 datasetOptions.clear();
2284 layerOptions.clear();
2287 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2288 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2293 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2294 QStringLiteral(
"SHAPE" )
2298 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2299 QStringLiteral(
"OBJECTID" )
2302 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2304 QStringLiteral(
"ESRI FileGDB" ),
2305 QObject::tr(
"ESRI FileGDB" ),
2306 QStringLiteral(
"*.gdb" ),
2307 QStringLiteral(
"gdb" ),
2310 QStringLiteral(
"UTF-8" )
2316 datasetOptions.clear();
2317 layerOptions.clear();
2320 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2321 "to STRING, all fields will be of String type." ),
2323 << QStringLiteral(
"AUTO" )
2324 << QStringLiteral(
"STRING" ),
2325 QStringLiteral(
"AUTO" ),
2330 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2331 "if the first line might be the name of columns. If set to FORCE, the driver "
2332 "will consider the first line as the header line. If set to "
2333 "DISABLE, it will be considered as the first feature. Otherwise "
2334 "auto-detection will occur." ),
2336 << QStringLiteral(
"FORCE" )
2337 << QStringLiteral(
"DISABLE" )
2338 << QStringLiteral(
"AUTO" ),
2339 QStringLiteral(
"AUTO" ),
2343 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2345 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2346 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2347 QStringLiteral(
"*.xlsx" ),
2348 QStringLiteral(
"xlsx" ),
2351 QStringLiteral(
"UTF-8" )
2356 datasetOptions.clear();
2357 layerOptions.clear();
2360 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2361 "to STRING, all fields will be of String type." ),
2363 << QStringLiteral(
"AUTO" )
2364 << QStringLiteral(
"STRING" ),
2365 QStringLiteral(
"AUTO" ),
2370 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2371 "if the first line might be the name of columns. If set to FORCE, the driver "
2372 "will consider the first line as the header line. If set to "
2373 "DISABLE, it will be considered as the first feature. Otherwise "
2374 "auto-detection will occur." ),
2376 << QStringLiteral(
"FORCE" )
2377 << QStringLiteral(
"DISABLE" )
2378 << QStringLiteral(
"AUTO" ),
2379 QStringLiteral(
"AUTO" ),
2383 driverMetadata.insert( QStringLiteral(
"ODS" ),
2385 QStringLiteral(
"Open Document Spreadsheet" ),
2386 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2387 QStringLiteral(
"*.ods" ),
2388 QStringLiteral(
"ods" ),
2391 QStringLiteral(
"UTF-8" )
2396 datasetOptions.clear();
2397 layerOptions.clear();
2400 QObject::tr(
"Compression method." ),
2402 << QStringLiteral(
"UNCOMPRESSED" )
2403 << QStringLiteral(
"SNAPPY" ),
2404 QStringLiteral(
"SNAPPY" ),
2409 QObject::tr(
"Geometry encoding." ),
2411 << QStringLiteral(
"WKB" )
2412 << QStringLiteral(
"WKT" )
2413 << QStringLiteral(
"GEOARROW" ),
2414 QStringLiteral(
"WKB" ),
2419 QObject::tr(
"Maximum number of rows per group." ),
2424 QObject::tr(
"Name for the feature identifier column" ),
2429 QObject::tr(
"Name for the geometry column" ),
2430 QStringLiteral(
"geometry" )
2434 QObject::tr(
"Name of the coordinate system for the edges." ),
2436 << QStringLiteral(
"PLANAR" )
2437 << QStringLiteral(
"SPHERICAL" ),
2438 QStringLiteral(
"PLANAR" ),
2442 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2444 QStringLiteral(
"(Geo)Parquet" ),
2445 QObject::tr(
"(Geo)Parquet" ),
2446 QStringLiteral(
"*.parquet" ),
2447 QStringLiteral(
"parquet" ),
2450 QStringLiteral(
"UTF-8" )
2455 datasetOptions.clear();
2456 layerOptions.clear();
2459 QObject::tr(
"Line termination character sequence." ),
2461 << QStringLiteral(
"CRLF" )
2462 << QStringLiteral(
"LF" ),
2463 QStringLiteral(
"LF" ),
2469 QObject::tr(
"Format of geometry columns." ),
2471 << QStringLiteral(
"geometry" )
2472 << QStringLiteral(
"geography" ),
2473 QStringLiteral(
"geometry" ),
2478 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2479 "Laundered names will be converted to lower case and some special "
2480 "characters(' - #) will be changed to underscores." ),
2485 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2486 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2489 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2492 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2497 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2502 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2504 << QStringLiteral(
"YES" )
2505 << QStringLiteral(
"NO" )
2506 << QStringLiteral(
"IF_EXISTS" ),
2507 QStringLiteral(
"YES" ),
2512 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2513 "When this option isn't specified and that a SRS is associated with the "
2514 "layer, a search is made in the spatial_ref_sys to find a match for the "
2515 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2516 "the spatial_ref_sys table. When the SRID option is specified, this "
2517 "search (and the eventual insertion of a new entry) will not be done: "
2518 "the specified SRID is used as such." ),
2523 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2524 "Important to set it correctly if using non-linear geometry types" ),
2525 QStringLiteral(
"2.2" )
2528 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2530 QStringLiteral(
"PostgreSQL SQL dump" ),
2531 QObject::tr(
"PostgreSQL SQL dump" ),
2532 QStringLiteral(
"*.sql" ),
2533 QStringLiteral(
"sql" ),
2536 QStringLiteral(
"UTF-8" )
2542 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2543 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2544 ~QgsVectorFileWriterMetadataContainer()
2546 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2548 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2549 delete optionIt.value();
2550 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2551 delete optionIt.value();
2555 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2562 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2563 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2565 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2567 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2568 driverName != QLatin1String(
"PGDUMP" ) &&
2569 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2574 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2589 return QStringList();
2598 return QStringList();
2605 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2636 return mCapabilities;
2646 QgsFeatureList::iterator fIt = features.begin();
2648 for ( ; fIt != features.end(); ++fIt )
2673 QString styleString;
2674 QString currentStyle;
2676 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2677 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2679 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2680 for (
int i = 0; i < nSymbolLayers; ++i )
2683 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2689 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2690 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2692 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2698 if ( symbolIt != symbols.constBegin() || i != 0 )
2700 styleString.append(
';' );
2702 styleString.append( currentStyle );
2707 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2708 if ( !writeFeature(
mLayer, poFeature.get() ) )
2720 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2728 if ( !writeFeature(
mLayer, poFeature.get() ) )
2752 int fldIdx = it.key();
2753 int ogrField = it.value();
2755 QVariant attrValue = feature.
attribute( fldIdx );
2760 OGR_F_UnsetField( poFeature.get(), ogrField );
2773 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2788 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2789 .arg( feature.
attribute( fldIdx ).toString(),
2796 switch ( field.
type() )
2798 case QMetaType::Type::Int:
2799 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2801 case QMetaType::Type::LongLong:
2802 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2804 case QMetaType::Type::Bool:
2805 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2807 case QMetaType::Type::QString:
2808 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2810 case QMetaType::Type::Double:
2811 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2813 case QMetaType::Type::QDate:
2814 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2815 attrValue.toDate().year(),
2816 attrValue.toDate().month(),
2817 attrValue.toDate().day(),
2820 case QMetaType::Type::QDateTime:
2823 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2827 const QDateTime dt = attrValue.toDateTime();
2828 const QDate date = dt.date();
2829 const QTime time = dt.time();
2830 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2836 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2840 case QMetaType::Type::QTime:
2843 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2847 const QTime time = attrValue.toTime();
2848 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2852 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2857 case QMetaType::Type::QByteArray:
2859 const QByteArray ba = attrValue.toByteArray();
2860 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2864 case QMetaType::Type::UnknownType:
2867 case QMetaType::Type::QStringList:
2872 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2874 if ( !doc.isNull() )
2876 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2878 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2882 QStringList list = attrValue.toStringList();
2883 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2885 int count = list.count();
2886 char **lst =
new char *[count + 1];
2890 for (
const QString &
string : list )
2892 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2896 lst[count] =
nullptr;
2897 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2902 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2907 case QMetaType::Type::QVariantList:
2911 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2913 if ( !doc.isNull() )
2915 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2917 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2922 if ( field.
subType() == QMetaType::Type::QString )
2924 QStringList list = attrValue.toStringList();
2925 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2927 int count = list.count();
2928 char **lst =
new char *[count + 1];
2932 for (
const QString &
string : list )
2934 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2938 lst[count] =
nullptr;
2939 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2944 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2948 else if ( field.
subType() == QMetaType::Type::Int )
2950 const QVariantList list = attrValue.toList();
2951 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
2953 const int count = list.count();
2954 int *lst =
new int[count];
2958 for (
const QVariant &value : list )
2960 lst[pos] = value.toInt();
2964 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2969 QStringList strings;
2970 strings.reserve( list.size() );
2971 for (
const QVariant &value : list )
2973 strings << QString::number( value.toInt() );
2975 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2979 else if ( field.
subType() == QMetaType::Type::Double )
2981 const QVariantList list = attrValue.toList();
2982 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
2984 const int count = list.count();
2985 double *lst =
new double[count];
2989 for (
const QVariant &value : list )
2991 lst[pos] = value.toDouble();
2995 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3000 QStringList strings;
3001 strings.reserve( list.size() );
3002 for (
const QVariant &value : list )
3004 strings << QString::number( value.toDouble() );
3006 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3010 else if ( field.
subType() == QMetaType::Type::LongLong )
3012 const QVariantList list = attrValue.toList();
3013 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3015 const int count = list.count();
3016 long long *lst =
new long long[count];
3020 for (
const QVariant &value : list )
3022 lst[pos] = value.toLongLong();
3026 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3031 QStringList strings;
3032 strings.reserve( list.size() );
3033 for (
const QVariant &value : list )
3035 strings << QString::number( value.toLongLong() );
3037 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3044 case QMetaType::Type::QVariantMap:
3047 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3048 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3050 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3052 if ( !doc.isNull() )
3054 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3055 jsonString = QString::fromUtf8( json.data() );
3057 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3067 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
3070 .arg( attrValue.typeName(),
3071 attrValue.toString() );
3084 if ( mCoordinateTransform )
3089 geom.
transform( *mCoordinateTransform );
3107 OGRGeometryH mGeom2 =
nullptr;
3136 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3143 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3163 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3164 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3174 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3175 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3176 if ( err != OGRERR_NONE )
3178 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3179 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3186 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3194 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3196 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3197 if ( err != OGRERR_NONE )
3199 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3200 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3207 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3222 for (
int i = 0; i < attributes.size(); i++ )
3224 if ( omap.find( i ) != omap.end() )
3229bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3231 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3233 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3243 if ( mUsingTransaction )
3245 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3247 QgsDebugError( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3260 const QString &fileName,
3261 const QString &fileEncoding,
3263 const QString &driverName,
3265 QString *errorMessage,
3266 const QStringList &datasourceOptions,
3267 const QStringList &layerOptions,
3268 bool skipAttributeCreation,
3269 QString *newFilename,
3271 double symbologyScale,
3281 if ( destCRS.
isValid() && layer )
3307 const QString &fileName,
3308 const QString &fileEncoding,
3310 const QString &driverName,
3312 QString *errorMessage,
3313 const QStringList &datasourceOptions,
3314 const QStringList &layerOptions,
3315 bool skipAttributeCreation,
3316 QString *newFilename,
3318 double symbologyScale,
3349 : driverName( QStringLiteral(
"GPKG" ) )
3357 if ( !layer || !layer->
isValid() )
3364 details.sourceCrs = layer->
crs();
3365 details.sourceWkbType = layer->
wkbType();
3366 details.sourceFields = layer->
fields();
3375 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3383 details.geometryTypeScanIterator = layer->
getFeatures( req );
3387 details.renderContext.setExpressionContext( details.expressionContext );
3388 details.renderContext.setRendererScale( options.
symbologyScale );
3390 details.shallTransform =
false;
3395 details.shallTransform =
true;
3400 details.outputCrs = details.sourceCrs;
3403 details.destWkbType = details.sourceWkbType;
3417 details.attributes.clear();
3418 else if ( details.attributes.isEmpty() )
3420 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3421 for (
int idx : allAttributes )
3423 QgsField fld = details.sourceFields.at( idx );
3424 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3426 details.attributes.append( idx );
3430 if ( !details.attributes.isEmpty() )
3432 for (
int attrIdx : std::as_const( details.attributes ) )
3434 if ( details.sourceFields.exists( attrIdx ) )
3436 QgsField field = details.sourceFields.at( attrIdx );
3438 details.outputFields.append( field );
3442 QgsDebugError( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3449 if ( details.providerType == QLatin1String(
"spatialite" ) )
3451 for (
int i = 0; i < details.outputFields.size(); i++ )
3453 if ( details.outputFields.at( i ).type() == QMetaType::Type::LongLong )
3458 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3460 details.outputFields[i].setType( QMetaType::Type::Int );
3468 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3478 bool useFilterRect =
true;
3479 if ( details.shallTransform )
3490 useFilterRect =
false;
3493 if ( useFilterRect )
3499 details.filterRectEngine->prepareGeometry();
3501 details.sourceFeatureIterator = layer->
getFeatures( req );
3520 int lastProgressReport = 0;
3521 long long total = details.featureCount;
3524 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3526 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3527 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3531 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3532 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3533 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3534 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3537 *
errorMessage = QObject::tr(
"Cannot overwrite an OGR layer in place" );
3557 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3558 if ( newProgress != lastProgressReport )
3560 lastProgressReport = newProgress;
3575 QString tempNewFilename;
3576 QString tempNewLayer;
3584 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
3588 *newFilename = tempNewFilename;
3591 *newLayer = tempNewLayer;
3620 switch ( writer->symbologyExport() )
3638 int n = 0, errors = 0;
3647 writer->startRender( details.renderer.get(), details.sourceFields );
3649 writer->resetMap( details.attributes );
3651 writer->mFields = details.sourceFields;
3655 int initialProgress = lastProgressReport;
3656 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3667 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3668 if ( newProgress < 100 && newProgress != lastProgressReport )
3670 lastProgressReport = newProgress;
3675 if ( details.shallTransform )
3688 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
3689 .arg( fet.
id() ).arg( e.
what() );
3706 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3713 *
errorMessage = QObject::tr(
"Feature write errors:" );
3719 if ( errors > 1000 )
3723 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3733 writer->stopRender();
3737 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3742 bool metadataFailure =
false;
3747 {QStringLiteral(
"path" ), tempNewFilename },
3748 {QStringLiteral(
"layerName" ), tempNewLayer }
3762 metadataFailure =
true;
3773 metadataFailure =
true;
3781 const QString &fileName,
3783 QString *newFilename,
3787 QgsVectorFileWriter::PreparedWriterDetails details;
3788 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3796 const QString &fileName,
3799 QString *newFilename,
3803 QgsVectorFileWriter::PreparedWriterDetails details;
3804 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3813 QgsVectorFileWriter::PreparedWriterDetails details;
3814 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3823 QFileInfo fi( fileName );
3824 QDir dir = fi.dir();
3827 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3829 filter << fi.completeBaseName() + suffix;
3833 const auto constEntryList = dir.entryList( filter );
3834 for (
const QString &file : constEntryList )
3836 QFile f( dir.canonicalPath() +
'/' + file );
3839 QgsDebugError( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3855 QStringList driverNames;
3858 for (
int i = 0; i < GDALGetDriverCount(); ++i )
3860 GDALDriverH
driver = GDALGetDriver( i );
3867 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
3868 if ( driverExtensions.isEmpty() )
3871 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
3872 if ( splitExtensions.intersects( multiLayerExtensions ) )
3874 driverNames << GDALGetDescription(
driver );
3882 static QReadWriteLock sFilterLock;
3883 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3887 const auto it = sFilters.constFind( options );
3888 if ( it != sFilters.constEnd() )
3892 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3895 int const drvCount = OGRGetDriverCount();
3899 for (
int i = 0; i < drvCount; ++i )
3901 OGRSFDriverH drv = OGRGetDriver( i );
3904 const QString drvName = GDALGetDescription( drv );
3908 if ( !multiLayerDrivers.contains( drvName ) )
3912 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3913 bool nonSpatialFormat =
false;
3916 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr );
3919 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3924 if ( nonSpatialFormat )
3929 if ( filterString.isEmpty() )
3936 globs = metadata.
glob.toLower().split(
' ' );
3942 details.
globs = globs;
3951 if ( options & SortRecommended )
3953 if ( a.driverName == QLatin1String(
"GPKG" ) )
3955 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3957 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3959 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3966 sFilters.insert( options, results );
3973 QSet< QString > extensions;
3975 const thread_local QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3979 for (
const QString &glob : format.globs )
3981 const QRegularExpressionMatch match = rx.match( glob );
3982 if ( !match.hasMatch() )
3985 const QString matched = match.captured( 1 );
3986 extensions.insert( matched );
3990 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3992 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3994 if ( options & SortRecommended )
3996 if ( a == QLatin1String(
"gpkg" ) )
3998 else if ( b == QLatin1String(
"gpkg" ) )
4000 else if ( a == QLatin1String(
"shp" ) )
4002 else if ( b == QLatin1String(
"shp" ) )
4006 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4009 return extensionList;
4014 QList< QgsVectorFileWriter::DriverDetails > results;
4017 const int drvCount = OGRGetDriverCount();
4021 QStringList writableDrivers;
4022 for (
int i = 0; i < drvCount; ++i )
4024 OGRSFDriverH drv = OGRGetDriver( i );
4027 const QString drvName = GDALGetDescription( drv );
4031 if ( !multiLayerDrivers.contains( drvName ) )
4039 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
4043 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
4045 writableDrivers << QStringLiteral(
"DBF file" );
4047 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4050 if ( drvName == QLatin1String(
"MapInfo File" ) )
4052 writableDrivers << QStringLiteral(
"MapInfo MIF" );
4054 else if ( drvName == QLatin1String(
"SQLite" ) )
4061 QString option = QStringLiteral(
"SPATIALITE=YES" );
4062 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4063 OGRSFDriverH poDriver;
4065 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4068 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
4071 writableDrivers << QStringLiteral(
"SpatiaLite" );
4072 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
4075 CPLFree( options[0] );
4077 writableDrivers << drvName;
4082 results.reserve( writableDrivers.count() );
4083 for (
const QString &drvName : std::as_const( writableDrivers ) )
4097 if ( options & SortRecommended )
4099 if ( a.driverName == QLatin1String(
"GPKG" ) )
4101 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4103 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4105 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4109 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4116 QString ext = extension.trimmed();
4117 if ( ext.isEmpty() )
4120 if ( ext.startsWith(
'.' ) )
4124 int const drvCount = GDALGetDriverCount();
4126 for (
int i = 0; i < drvCount; ++i )
4128 GDALDriverH drv = GDALGetDriver( i );
4134 QString drvName = GDALGetDriverShortName( drv );
4135 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4137 const auto constDriverExtensions = driverExtensions;
4138 for (
const QString &
driver : constDriverExtensions )
4140 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4151 QString filterString;
4155 if ( !filterString.isEmpty() )
4156 filterString += QLatin1String(
";;" );
4158 filterString += details.filterString;
4160 return filterString;
4169 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4170 metadata.
glob.toLower(),
4171 metadata.
glob.toUpper() );
4176 if ( codecName == QLatin1String(
"System" ) )
4177 return QStringLiteral(
"LDID/0" );
4179 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4180 const QRegularExpressionMatch match = re.match( codecName );
4181 if ( match.hasMatch() )
4183 QString
c = match.captured( 2 ).remove(
'-' );
4185 ( void )
c.toInt( &isNumber );
4213 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4214 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4217 int nTotalLevels = 0;
4219 QgsSymbolList::iterator symbolIt = symbolList.begin();
4220 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4222 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4223 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4225 int nLevels = ( *symbolIt )->symbolLayerCount();
4226 for (
int i = 0; i < nLevels; ++i )
4228 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4229 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4230 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4234 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4240 if ( !details.renderer )
4245 QHash< QgsSymbol *, QList<QgsFeature> > features;
4254 startRender( details.renderer.get(), details.sourceFields );
4274 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4285 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4286 if ( !featureSymbol )
4291 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4292 if ( it == features.end() )
4294 it = features.insert( featureSymbol, QList<QgsFeature>() );
4296 it.value().append( fet );
4301 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4302 for (
int i = 0; i < symbols.count(); i++ )
4308 if ( level < 0 || level >= 1000 )
4311 while ( level >= levels.count() )
4313 levels[level].append( item );
4318 int nTotalFeatures = 0;
4321 for (
int l = 0; l < levels.count(); l++ )
4324 for (
int i = 0; i < level.count(); i++ )
4327 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4328 if ( levelIt == features.end() )
4334 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4335 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4337 int llayer = item.
layer();
4338 QList<QgsFeature> &featureList = levelIt.value();
4339 QList<QgsFeature>::iterator featureIt = featureList.begin();
4340 for ( ; featureIt != featureList.end(); ++featureIt )
4350 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4351 if ( !styleString.isEmpty() )
4353 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4354 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4367 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4384 return 1000 / scale;
4401 return scale / 1000;
4409 mRenderer = createSymbologyRenderer( sourceRenderer );
4415 mRenderer->startRender( mRenderContext, fields );
4418void QgsVectorFileWriter::stopRender()
4425 mRenderer->stopRender( mRenderContext );
4428std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4441 if ( !sourceRenderer )
4446 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4453 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4454 for (
const QString &attr : rendererAttributes )
4459 attList.append( index );
4465QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4468 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4470 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4473 switch ( option->
type )
4480 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4490 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4500 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4507 if ( opt && !opt->
mValue.isEmpty() )
4509 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4520 OGRSFDriverH hDriver =
nullptr;
4524 const QString drvName = GDALGetDescription( hDriver );
4526 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4531 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4534 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4538 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4541 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4544 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4547 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4558 const QString &layerNameIn )
4560 OGRSFDriverH hDriver =
nullptr;
4565 QString layerName( layerNameIn );
4566 if ( layerName.isEmpty() )
4567 layerName = QFileInfo( datasetName ).baseName();
4569 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4574 const QString &layerName,
4578 OGRSFDriverH hDriver =
nullptr;
4582 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4588 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4589 const auto constAttributes = attributes;
4590 for (
int idx : constAttributes )
4593 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.
@ MultiPolygon25D
MultiPolygon25D.
@ GeometryCollectionZ
GeometryCollectionZ.
@ MultiLineString
MultiLineString.
@ MultiPolygonZ
MultiPolygonZ.
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.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Stores the component parts of a data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector 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.
int size() const
Returns number of items.
void clear()
Removes all fields.
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 ...
A geometry is the spatial representation of a feature.
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.
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())
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
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 int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
Custom exception class for provider connection related exceptions.
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.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage)
Saves metadata to the layer corresponding to the specified uri.
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.
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
Stores settings for use within QGIS.
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.
Represents a symbol level during vector rendering operations.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
Abstract base class for all rendered symbols.
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.
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.
A hidden option for file writing for a particular output format.
An available option for configuring file writing for a particular output format, presenting an intege...
Describes an available option for configuring file writing for a particular output format.
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...
A convenience class for writing vector layers to disk based formats (e.g.
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)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ 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.
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.
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.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
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.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
static Qgis::WkbType to25D(Qgis::WkbType type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static 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.
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.