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. "
1183 "This option also creates a .prj file which stores coordinate system information." ),
1188 QObject::tr(
"Field separator character." ),
1190 << QStringLiteral(
"COMMA" )
1191 << QStringLiteral(
"SEMICOLON" )
1192 << QStringLiteral(
"TAB" ),
1193 QStringLiteral(
"COMMA" )
1197 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1199 << QStringLiteral(
"IF_NEEDED" )
1200 << QStringLiteral(
"IF_AMBIGUOUS" )
1201 << QStringLiteral(
"ALWAYS" ),
1202 QStringLiteral(
"IF_AMBIGUOUS" )
1206 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1210 driverMetadata.insert( QStringLiteral(
"CSV" ),
1212 QStringLiteral(
"Comma Separated Value [CSV]" ),
1213 QObject::tr(
"Comma Separated Value [CSV]" ),
1214 QStringLiteral(
"*.csv" ),
1215 QStringLiteral(
"csv" ),
1222 datasetOptions.clear();
1223 layerOptions.clear();
1225 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1227 QStringLiteral(
"FlatGeobuf" ),
1228 QObject::tr(
"FlatGeobuf" ),
1229 QStringLiteral(
"*.fgb" ),
1230 QStringLiteral(
"fgb" ),
1233 QStringLiteral(
"UTF-8" )
1238 datasetOptions.clear();
1239 layerOptions.clear();
1242 QObject::tr(
"Override the type of shapefile created. "
1243 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1244 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1245 "MULTIPOINTZ for 3D;" ) +
1246 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1247 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1249 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1252 << QStringLiteral(
"NULL" )
1253 << QStringLiteral(
"POINT" )
1254 << QStringLiteral(
"ARC" )
1255 << QStringLiteral(
"POLYGON" )
1256 << QStringLiteral(
"MULTIPOINT" )
1257 << QStringLiteral(
"POINTZ" )
1258 << QStringLiteral(
"ARCZ" )
1259 << QStringLiteral(
"POLYGONZ" )
1260 << QStringLiteral(
"MULTIPOINTZ" )
1261 << QStringLiteral(
"POINTM" )
1262 << QStringLiteral(
"ARCM" )
1263 << QStringLiteral(
"POLYGONM" )
1264 << QStringLiteral(
"MULTIPOINTM" )
1265 << QStringLiteral(
"POINTZM" )
1266 << QStringLiteral(
"ARCZM" )
1267 << QStringLiteral(
"POLYGONZM" )
1268 << QStringLiteral(
"MULTIPOINTZM" )
1269 << QStringLiteral(
"MULTIPATCH" )
1279 QObject::tr(
"Set the encoding value in the DBF file. "
1280 "The default value is LDID/87. It is not clear "
1281 "what other values may be appropriate." ),
1289 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1293 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1295 QStringLiteral(
"ESRI Shapefile" ),
1296 QObject::tr(
"ESRI Shapefile" ),
1297 QStringLiteral(
"*.shp" ),
1298 QStringLiteral(
"shp" ),
1305 datasetOptions.clear();
1306 layerOptions.clear();
1308 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1310 QStringLiteral(
"DBF File" ),
1311 QObject::tr(
"DBF File" ),
1312 QStringLiteral(
"*.dbf" ),
1313 QStringLiteral(
"dbf" ),
1320 datasetOptions.clear();
1321 layerOptions.clear();
1324 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1325 "of the geometries at the feature and feature collection level." ),
1330 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1331 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1336 QObject::tr(
"Whether to use RFC 7946 standard. "
1337 "If disabled GeoJSON 2008 initial version will be used. "
1338 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1342 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1344 QStringLiteral(
"GeoJSON" ),
1345 QObject::tr(
"GeoJSON" ),
1346 QStringLiteral(
"*.geojson" ),
1347 QStringLiteral(
"geojson" ),
1350 QStringLiteral(
"UTF-8" )
1355 datasetOptions.clear();
1356 layerOptions.clear();
1359 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1360 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1365 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1366 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1367 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1371 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1373 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1374 QObject::tr(
"GeoJSON - Newline Delimited" ),
1375 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1376 QStringLiteral(
"geojsonl geojsons json" ),
1379 QStringLiteral(
"UTF-8" )
1384 datasetOptions.clear();
1385 layerOptions.clear();
1388 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1389 "Default value : RSS" ),
1391 << QStringLiteral(
"RSS" )
1392 << QStringLiteral(
"ATOM" ),
1393 QStringLiteral(
"RSS" )
1397 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1398 "W3C_GEO only supports point geometries. "
1399 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1401 << QStringLiteral(
"SIMPLE" )
1402 << QStringLiteral(
"GML" )
1403 << QStringLiteral(
"W3C_GEO" ),
1404 QStringLiteral(
"SIMPLE" )
1408 QObject::tr(
"If defined to YES, extension fields will be written. "
1409 "If the field name not found in the base schema matches "
1410 "the foo_bar pattern, foo will be considered as the namespace "
1411 "of the element, and a <foo:bar> element will be written. "
1412 "Otherwise, elements will be written in the <ogr:> namespace." ),
1417 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1418 "The user will have to provide the appropriate header and footer of the document." ),
1423 QObject::tr(
"XML content that will be put between the <channel> element and the "
1424 "first <item> element for a RSS document, or between the xml tag and "
1425 "the first <entry> element for an Atom document." ),
1430 QObject::tr(
"Value put inside the <title> element in the header. "
1431 "If not provided, a dummy value will be used as that element is compulsory." ),
1436 QObject::tr(
"Value put inside the <description> element in the header. "
1437 "If not provided, a dummy value will be used as that element is compulsory." ),
1442 QObject::tr(
"Value put inside the <link> element in the header. "
1443 "If not provided, a dummy value will be used as that element is compulsory." ),
1448 QObject::tr(
"Value put inside the <updated> element in the header. "
1449 "Should be formatted as a XML datetime. "
1450 "If not provided, a dummy value will be used as that element is compulsory." ),
1455 QObject::tr(
"Value put inside the <author><name> element in the header. "
1456 "If not provided, a dummy value will be used as that element is compulsory." ),
1461 QObject::tr(
"Value put inside the <id> element in the header. "
1462 "If not provided, a dummy value will be used as that element is compulsory." ),
1466 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1468 QStringLiteral(
"GeoRSS" ),
1469 QObject::tr(
"GeoRSS" ),
1470 QStringLiteral(
"*.xml" ),
1471 QStringLiteral(
"xml" ),
1474 QStringLiteral(
"UTF-8" )
1479 datasetOptions.clear();
1480 layerOptions.clear();
1483 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1484 "Note that the schema file isn't actually accessed by OGR, so it "
1485 "is up to the user to ensure it will match the schema of the OGR "
1486 "produced GML data file." ),
1491 QObject::tr(
"This writes a GML application schema file to a corresponding "
1492 ".xsd file (with the same basename). If INTERNAL is used the "
1493 "schema is written within the GML file, but this is experimental "
1494 "and almost certainly not valid XML. "
1495 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1497 << QStringLiteral(
"EXTERNAL" )
1498 << QStringLiteral(
"INTERNAL" )
1499 << QStringLiteral(
"OFF" ),
1500 QStringLiteral(
"EXTERNAL" )
1504 QObject::tr(
"This is the prefix for the application target namespace." ),
1505 QStringLiteral(
"ogr" )
1509 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1510 "application target namespace in the GML file." ),
1515 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1516 "This is the application target namespace." ),
1517 QStringLiteral(
"http://ogr.maptools.org/" )
1521 QObject::tr(
"GML version to use." ),
1523 << QStringLiteral(
"GML2" )
1524 << QStringLiteral(
"GML3" )
1525 << QStringLiteral(
"GML3Deegree" )
1526 << QStringLiteral(
"GML3.2" ),
1527 QStringLiteral(
"GML3.2" )
1531 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1532 "If YES, SRS with EPSG authority will be written with the "
1533 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1534 "geographic SRS without explicit AXIS order, but that the same "
1535 "SRS authority code imported with ImportFromEPSGA() should be "
1536 "treated as lat/long, then the function will take care of coordinate "
1537 "order swapping. If set to NO, SRS with EPSG authority will be "
1538 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1543 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1544 "If set to NO, the <gml:boundedBy> element will not be written for "
1550 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1551 "for more readability, but at the expense of file size." ),
1556 driverMetadata.insert( QStringLiteral(
"GML" ),
1558 QStringLiteral(
"Geography Markup Language [GML]" ),
1559 QObject::tr(
"Geography Markup Language [GML]" ),
1560 QStringLiteral(
"*.gml" ),
1561 QStringLiteral(
"gml" ),
1564 QStringLiteral(
"UTF-8" )
1569 datasetOptions.clear();
1570 layerOptions.clear();
1573 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1578 QObject::tr(
"Human-readable description for the layer content" ),
1583 QObject::tr(
"Name for the feature identifier column" ),
1584 QStringLiteral(
"fid" )
1588 QObject::tr(
"Name for the geometry column" ),
1589 QStringLiteral(
"geom" )
1593 QObject::tr(
"If a spatial index must be created." ),
1597 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1599 QStringLiteral(
"GeoPackage" ),
1600 QObject::tr(
"GeoPackage" ),
1601#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
1602 QStringLiteral(
"*.gpkg *.gpkg.zip" ),
1604 QStringLiteral(
"*.gpkg" ),
1606 QStringLiteral(
"gpkg" ),
1609 QStringLiteral(
"UTF-8" )
1614 datasetOptions.clear();
1615 layerOptions.clear();
1617 driverMetadata.insert( QStringLiteral(
"GMT" ),
1619 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1620 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1621 QStringLiteral(
"*.gmt" ),
1622 QStringLiteral(
"gmt" ),
1629 datasetOptions.clear();
1630 layerOptions.clear();
1633 QObject::tr(
"By default when writing a layer whose features are of "
1634 "type wkbLineString, the GPX driver chooses to write "
1635 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1636 "they will be written as tracks." ),
1641 QObject::tr(
"By default when writing a layer whose features are of "
1642 "type wkbMultiLineString, the GPX driver chooses to write "
1643 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1644 "they will be written as routes, provided that the multilines "
1645 "are composed of only one single line." ),
1650 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1651 "extra fields will be written inside the <extensions> tag." ),
1656 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1657 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1658 QStringLiteral(
"ogr" )
1662 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1663 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1664 QStringLiteral(
"http://osgeo.org/gdal" )
1668 QObject::tr(
"By default files are created with the line termination "
1669 "conventions of the local platform (CR/LF on win32 or LF "
1670 "on all other systems). This may be overridden through use "
1671 "of the LINEFORMAT layer creation option which may have a value "
1672 "of CRLF (DOS format) or LF (Unix format)." ),
1674 << QStringLiteral(
"CRLF" )
1675 << QStringLiteral(
"LF" ),
1680 driverMetadata.insert( QStringLiteral(
"GPX" ),
1682 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1683 QObject::tr(
"GPS eXchange Format [GPX]" ),
1684 QStringLiteral(
"*.gpx" ),
1685 QStringLiteral(
"gpx" ),
1688 QStringLiteral(
"UTF-8" )
1693 datasetOptions.clear();
1694 layerOptions.clear();
1696 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1698 QStringLiteral(
"INTERLIS 1" ),
1699 QObject::tr(
"INTERLIS 1" ),
1700 QStringLiteral(
"*.itf *.xml *.ili" ),
1701 QStringLiteral(
"ili" ),
1708 datasetOptions.clear();
1709 layerOptions.clear();
1711 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1713 QStringLiteral(
"INTERLIS 2" ),
1714 QObject::tr(
"INTERLIS 2" ),
1715 QStringLiteral(
"*.xtf *.xml *.ili" ),
1716 QStringLiteral(
"ili" ),
1723 datasetOptions.clear();
1724 layerOptions.clear();
1727 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1728 QStringLiteral(
"Name" )
1732 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1733 QStringLiteral(
"Description" )
1737 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1738 "This will only affect 3D geometries and must be one of the valid KML options." ),
1740 << QStringLiteral(
"clampToGround" )
1741 << QStringLiteral(
"relativeToGround" )
1742 << QStringLiteral(
"absolute" ),
1743 QStringLiteral(
"relativeToGround" )
1747 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1748 "the id of the root <Document> node. The default value is root_doc." ),
1749 QStringLiteral(
"root_doc" )
1752 driverMetadata.insert( QStringLiteral(
"KML" ),
1754 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1755 QObject::tr(
"Keyhole Markup Language [KML]" ),
1756 QStringLiteral(
"*.kml" ),
1757 QStringLiteral(
"kml" ),
1760 QStringLiteral(
"UTF-8" )
1765 datasetOptions.clear();
1766 layerOptions.clear();
1768 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1771 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1772 "In this mode writing files can be about 5 times faster, "
1773 "but spatial queries can be up to 30 times slower." ),
1775 << QStringLiteral(
"QUICK" )
1776 << QStringLiteral(
"OPTIMIZED" ),
1777 QStringLiteral(
"QUICK" ),
1782 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1783 "to 512. MapInfo 15.2 and above creates .tab files with a "
1784 "blocksize of 16384 bytes. Any MapInfo version should be "
1785 "able to handle block sizes from 512 to 32256." ),
1789 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1790 "accuracy of the coordinates. Note: the geometry of written "
1791 "features must be within the defined box." ),
1795 insertMapInfoOptions( datasetOptions, layerOptions );
1797 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1799 QStringLiteral(
"Mapinfo" ),
1800 QObject::tr(
"Mapinfo TAB" ),
1801 QStringLiteral(
"*.tab" ),
1802 QStringLiteral(
"tab" ),
1807 datasetOptions.clear();
1808 layerOptions.clear();
1809 insertMapInfoOptions( datasetOptions, layerOptions );
1812 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1814 QStringLiteral(
"Mapinfo" ),
1815 QObject::tr(
"Mapinfo MIF" ),
1816 QStringLiteral(
"*.mif" ),
1817 QStringLiteral(
"mif" ),
1824 datasetOptions.clear();
1825 layerOptions.clear();
1828 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1829 "seed file should be used. This option is ignored if the SEED option is provided." ),
1834 QObject::tr(
"Override the seed file to use." ),
1839 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1840 "If not, only the first three elements will be copied." ),
1845 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1850 QObject::tr(
"Override the master unit name from the seed file with "
1851 "the provided one or two character unit name." ),
1856 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1857 "one or two character unit name." ),
1862 QObject::tr(
"Override the number of subunits per master unit. "
1863 "By default the seed file value is used." ),
1868 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1869 "per sub unit. By default the seed file value is used." ),
1874 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1875 "By default the origin from the seed file is used." ),
1879 driverMetadata.insert( QStringLiteral(
"DGN" ),
1881 QStringLiteral(
"Microstation DGN" ),
1882 QObject::tr(
"Microstation DGN" ),
1883 QStringLiteral(
"*.dgn" ),
1884 QStringLiteral(
"dgn" ),
1891 datasetOptions.clear();
1892 layerOptions.clear();
1895 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1897 << QStringLiteral(
"APPLY" )
1898 << QStringLiteral(
"IGNORE" ),
1899 QStringLiteral(
"APPLY" )
1903 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1904 "Multipoint geometries are not well handled by many formats, "
1905 "so it can be convenient to split single sounding features with many points "
1906 "into many single point features." ),
1911 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1912 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1918 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1919 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1924 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1925 "be preserved as a special numeric value. This option should not generally "
1926 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1931 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1932 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1937 QObject::tr(
"Should additional attributes relating features to their underlying "
1938 "geometric primitives be attached. These are the values of the FSPT group, "
1939 "and are primarily needed when doing S-57 to S-57 translations." ),
1944 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1945 "specified in the S57 DSSI record." ),
1951 driverMetadata.insert( QStringLiteral(
"S57" ),
1953 QStringLiteral(
"S-57 Base file" ),
1954 QObject::tr(
"S-57 Base file" ),
1955 QStringLiteral(
"*.000" ),
1956 QStringLiteral(
"000" ),
1963 datasetOptions.clear();
1964 layerOptions.clear();
1966 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1968 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1969 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1970 QStringLiteral(
"*catd.ddf" ),
1971 QStringLiteral(
"ddf" ),
1978 datasetOptions.clear();
1979 layerOptions.clear();
1982 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1983 "tables in a new database. By default these metadata tables are created "
1984 "when a new database is created." ),
1990 QStringLiteral(
"NO" )
1995 QStringLiteral(
"NO" )
1999 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
2000 "This is generally more space and processing efficient, but harder "
2001 "to inspect or use in simple applications than WKT (Well Known Text)." ),
2003 << QStringLiteral(
"WKB" )
2004 << QStringLiteral(
"WKT" ),
2005 QStringLiteral(
"WKB" )
2009 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2010 "in SQLite. Laundered names will be converted to lower case and some special "
2011 "characters(' - #) will be changed to underscores." ),
2016 QStringLiteral(
"NO" )
2020 QStringLiteral(
"NO" )
2028 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2029 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2030 "for databases that have big string blobs. However, use with care, since "
2031 "the value of such columns will be seen as compressed binary content with "
2032 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2033 "modifying or querying compressed columns, compression/decompression is "
2034 "done transparently. However, such columns cannot be (easily) queried with "
2035 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2036 "have the 'VARCHAR_deflate' declaration type." ),
2040 driverMetadata.insert( QStringLiteral(
"SQLite" ),
2042 QStringLiteral(
"SQLite" ),
2043 QObject::tr(
"SQLite" ),
2044 QStringLiteral(
"*.sqlite" ),
2045 QStringLiteral(
"sqlite" ),
2048 QStringLiteral(
"UTF-8" )
2053 datasetOptions.clear();
2054 layerOptions.clear();
2057 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2058 "tables in a new database. By default these metadata tables are created "
2059 "when a new database is created." ),
2064 QStringLiteral(
"YES" )
2068 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2069 "Set to NO for regular SQLite databases." ),
2074 QStringLiteral(
"SPATIALITE" )
2078 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2079 "in SQLite. Laundered names will be converted to lower case and some special "
2080 "characters(' - #) will be changed to underscores." ),
2085 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2086 "against libspatialite, this option can be used to control if a spatial "
2087 "index must be created." ),
2092 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2093 "this option can be used to control if the compressed format for "
2094 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2099 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2100 "When this option isn't specified and that a SRS is associated with the "
2101 "layer, a search is made in the spatial_ref_sys to find a match for the "
2102 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2103 "the spatial_ref_sys table. When the SRID option is specified, this "
2104 "search (and the eventual insertion of a new entry) will not be done: "
2105 "the specified SRID is used as such." ),
2110 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2111 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2112 "for databases that have big string blobs. However, use with care, since "
2113 "the value of such columns will be seen as compressed binary content with "
2114 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2115 "modifying or queryings compressed columns, compression/decompression is "
2116 "done transparently. However, such columns cannot be (easily) queried with "
2117 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2118 "have the 'VARCHAR_deflate' declaration type." ),
2122 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2124 QStringLiteral(
"SpatiaLite" ),
2125 QObject::tr(
"SpatiaLite" ),
2126 QStringLiteral(
"*.sqlite" ),
2127 QStringLiteral(
"sqlite" ),
2130 QStringLiteral(
"UTF-8" )
2134 datasetOptions.clear();
2135 layerOptions.clear();
2138 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2143 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2147 driverMetadata.insert( QStringLiteral(
"DXF" ),
2149 QStringLiteral(
"AutoCAD DXF" ),
2150 QObject::tr(
"AutoCAD DXF" ),
2151 QStringLiteral(
"*.dxf" ),
2152 QStringLiteral(
"dxf" ),
2159 datasetOptions.clear();
2160 layerOptions.clear();
2163 QObject::tr(
"Indicates the GeoConcept export file extension. "
2164 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2166 << QStringLiteral(
"GXT" )
2167 << QStringLiteral(
"TXT" ),
2168 QStringLiteral(
"GXT" )
2172 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2173 "In this file, every line must start with //# followed by a keyword. "
2174 "Lines starting with // are comments." ),
2179 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2180 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2181 "the Name found in the GCT file for a sub-type section within the previous "
2186 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2188 QStringLiteral(
"Geoconcept" ),
2189 QObject::tr(
"Geoconcept" ),
2190 QStringLiteral(
"*.gxt *.txt" ),
2191 QStringLiteral(
"gxt" ),
2198 datasetOptions.clear();
2199 layerOptions.clear();
2201#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0)
2203 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." ),
2205 << QStringLiteral(
"ALL" )
2206 << QStringLiteral(
"ARCGIS_PRO_3_2_OR_LATER" ),
2207 QStringLiteral(
"ALL" )
2212 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2213 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2218 QObject::tr(
"Set layer name alias." ),
2223 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2224 QStringLiteral(
"SHAPE" )
2228 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'." ),
2233 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2234 QStringLiteral(
"OBJECTID" )
2250 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." ),
2255 QObject::tr(
"XML documentation for the layer." ),
2259 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2260 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2261 QStringLiteral(
"DEFAULTS" ),
2266 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." ),
2270 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2272 QStringLiteral(
"ESRI File Geodatabase" ),
2273 QObject::tr(
"ESRI File Geodatabase" ),
2274 QStringLiteral(
"*.gdb" ),
2275 QStringLiteral(
"gdb" ),
2278 QStringLiteral(
"UTF-8" )
2282#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,11,0)
2284 datasetOptions.clear();
2285 layerOptions.clear();
2288 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2289 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2294 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2295 QStringLiteral(
"SHAPE" )
2299 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2300 QStringLiteral(
"OBJECTID" )
2303 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2305 QStringLiteral(
"ESRI FileGDB" ),
2306 QObject::tr(
"ESRI FileGDB" ),
2307 QStringLiteral(
"*.gdb" ),
2308 QStringLiteral(
"gdb" ),
2311 QStringLiteral(
"UTF-8" )
2317 datasetOptions.clear();
2318 layerOptions.clear();
2321 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2322 "to STRING, all fields will be of String type." ),
2324 << QStringLiteral(
"AUTO" )
2325 << QStringLiteral(
"STRING" ),
2326 QStringLiteral(
"AUTO" ),
2331 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2332 "if the first line might be the name of columns. If set to FORCE, the driver "
2333 "will consider the first line as the header line. If set to "
2334 "DISABLE, it will be considered as the first feature. Otherwise "
2335 "auto-detection will occur." ),
2337 << QStringLiteral(
"FORCE" )
2338 << QStringLiteral(
"DISABLE" )
2339 << QStringLiteral(
"AUTO" ),
2340 QStringLiteral(
"AUTO" ),
2344 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2346 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2347 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2348 QStringLiteral(
"*.xlsx" ),
2349 QStringLiteral(
"xlsx" ),
2352 QStringLiteral(
"UTF-8" )
2357 datasetOptions.clear();
2358 layerOptions.clear();
2361 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2362 "to STRING, all fields will be of String type." ),
2364 << QStringLiteral(
"AUTO" )
2365 << QStringLiteral(
"STRING" ),
2366 QStringLiteral(
"AUTO" ),
2371 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2372 "if the first line might be the name of columns. If set to FORCE, the driver "
2373 "will consider the first line as the header line. If set to "
2374 "DISABLE, it will be considered as the first feature. Otherwise "
2375 "auto-detection will occur." ),
2377 << QStringLiteral(
"FORCE" )
2378 << QStringLiteral(
"DISABLE" )
2379 << QStringLiteral(
"AUTO" ),
2380 QStringLiteral(
"AUTO" ),
2384 driverMetadata.insert( QStringLiteral(
"ODS" ),
2386 QStringLiteral(
"Open Document Spreadsheet" ),
2387 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2388 QStringLiteral(
"*.ods" ),
2389 QStringLiteral(
"ods" ),
2392 QStringLiteral(
"UTF-8" )
2397 datasetOptions.clear();
2398 layerOptions.clear();
2401 QObject::tr(
"Compression method." ),
2403 << QStringLiteral(
"UNCOMPRESSED" )
2404 << QStringLiteral(
"SNAPPY" ),
2405 QStringLiteral(
"SNAPPY" ),
2410 QObject::tr(
"Geometry encoding." ),
2412 << QStringLiteral(
"WKB" )
2413 << QStringLiteral(
"WKT" )
2414 << QStringLiteral(
"GEOARROW" ),
2415 QStringLiteral(
"WKB" ),
2420 QObject::tr(
"Maximum number of rows per group." ),
2425 QObject::tr(
"Name for the feature identifier column" ),
2430 QObject::tr(
"Name for the geometry column" ),
2431 QStringLiteral(
"geometry" )
2435 QObject::tr(
"Name of the coordinate system for the edges." ),
2437 << QStringLiteral(
"PLANAR" )
2438 << QStringLiteral(
"SPHERICAL" ),
2439 QStringLiteral(
"PLANAR" ),
2443 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2445 QStringLiteral(
"(Geo)Parquet" ),
2446 QObject::tr(
"(Geo)Parquet" ),
2447 QStringLiteral(
"*.parquet" ),
2448 QStringLiteral(
"parquet" ),
2451 QStringLiteral(
"UTF-8" )
2456 datasetOptions.clear();
2457 layerOptions.clear();
2460 QObject::tr(
"Line termination character sequence." ),
2462 << QStringLiteral(
"CRLF" )
2463 << QStringLiteral(
"LF" ),
2464 QStringLiteral(
"LF" ),
2470 QObject::tr(
"Format of geometry columns." ),
2472 << QStringLiteral(
"geometry" )
2473 << QStringLiteral(
"geography" ),
2474 QStringLiteral(
"geometry" ),
2479 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2480 "Laundered names will be converted to lower case and some special "
2481 "characters(' - #) will be changed to underscores." ),
2486 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2487 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2490 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2493 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2498 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2503 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2505 << QStringLiteral(
"YES" )
2506 << QStringLiteral(
"NO" )
2507 << QStringLiteral(
"IF_EXISTS" ),
2508 QStringLiteral(
"YES" ),
2513 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2514 "When this option isn't specified and that a SRS is associated with the "
2515 "layer, a search is made in the spatial_ref_sys to find a match for the "
2516 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2517 "the spatial_ref_sys table. When the SRID option is specified, this "
2518 "search (and the eventual insertion of a new entry) will not be done: "
2519 "the specified SRID is used as such." ),
2524 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2525 "Important to set it correctly if using non-linear geometry types" ),
2526 QStringLiteral(
"2.2" )
2529 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2531 QStringLiteral(
"PostgreSQL SQL dump" ),
2532 QObject::tr(
"PostgreSQL SQL dump" ),
2533 QStringLiteral(
"*.sql" ),
2534 QStringLiteral(
"sql" ),
2537 QStringLiteral(
"UTF-8" )
2543 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2544 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2545 ~QgsVectorFileWriterMetadataContainer()
2547 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2549 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2550 delete optionIt.value();
2551 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2552 delete optionIt.value();
2556 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2563 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2564 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2566 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2568 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2569 driverName != QLatin1String(
"PGDUMP" ) &&
2570 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2575 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2590 return QStringList();
2599 return QStringList();
2606 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2637 return mCapabilities;
2647 QgsFeatureList::iterator fIt = features.begin();
2649 for ( ; fIt != features.end(); ++fIt )
2674 QString styleString;
2675 QString currentStyle;
2677 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2678 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2680 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2681 for (
int i = 0; i < nSymbolLayers; ++i )
2684 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2690 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2691 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2693 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2699 if ( symbolIt != symbols.constBegin() || i != 0 )
2701 styleString.append(
';' );
2703 styleString.append( currentStyle );
2708 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2709 if ( !writeFeature(
mLayer, poFeature.get() ) )
2721 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2729 if ( !writeFeature(
mLayer, poFeature.get() ) )
2753 int fldIdx = it.key();
2754 int ogrField = it.value();
2756 QVariant attrValue = feature.
attribute( fldIdx );
2761 OGR_F_UnsetField( poFeature.get(), ogrField );
2774 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2789 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2790 .arg( feature.
attribute( fldIdx ).toString(),
2797 switch ( field.
type() )
2799 case QMetaType::Type::Int:
2800 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2802 case QMetaType::Type::LongLong:
2803 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2805 case QMetaType::Type::Bool:
2806 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2808 case QMetaType::Type::QString:
2809 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2811 case QMetaType::Type::Double:
2812 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2814 case QMetaType::Type::QDate:
2815 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2816 attrValue.toDate().year(),
2817 attrValue.toDate().month(),
2818 attrValue.toDate().day(),
2821 case QMetaType::Type::QDateTime:
2824 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2828 const QDateTime dt = attrValue.toDateTime();
2829 const QDate date = dt.date();
2830 const QTime time = dt.time();
2831 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2837 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2841 case QMetaType::Type::QTime:
2844 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2848 const QTime time = attrValue.toTime();
2849 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2853 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2858 case QMetaType::Type::QByteArray:
2860 const QByteArray ba = attrValue.toByteArray();
2861 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2865 case QMetaType::Type::UnknownType:
2868 case QMetaType::Type::QStringList:
2873 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2875 if ( !doc.isNull() )
2877 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2879 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2883 QStringList list = attrValue.toStringList();
2884 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2886 int count = list.count();
2887 char **lst =
new char *[count + 1];
2891 for (
const QString &
string : list )
2893 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2897 lst[count] =
nullptr;
2898 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2903 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2908 case QMetaType::Type::QVariantList:
2912 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2914 if ( !doc.isNull() )
2916 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2918 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2923 if ( field.
subType() == QMetaType::Type::QString )
2925 QStringList list = attrValue.toStringList();
2926 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2928 int count = list.count();
2929 char **lst =
new char *[count + 1];
2933 for (
const QString &
string : list )
2935 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2939 lst[count] =
nullptr;
2940 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2945 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2949 else if ( field.
subType() == QMetaType::Type::Int )
2951 const QVariantList list = attrValue.toList();
2952 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
2954 const int count = list.count();
2955 int *lst =
new int[count];
2959 for (
const QVariant &value : list )
2961 lst[pos] = value.toInt();
2965 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
2970 QStringList strings;
2971 strings.reserve( list.size() );
2972 for (
const QVariant &value : list )
2974 strings << QString::number( value.toInt() );
2976 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
2980 else if ( field.
subType() == QMetaType::Type::Double )
2982 const QVariantList list = attrValue.toList();
2983 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
2985 const int count = list.count();
2986 double *lst =
new double[count];
2990 for (
const QVariant &value : list )
2992 lst[pos] = value.toDouble();
2996 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3001 QStringList strings;
3002 strings.reserve( list.size() );
3003 for (
const QVariant &value : list )
3005 strings << QString::number( value.toDouble() );
3007 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3011 else if ( field.
subType() == QMetaType::Type::LongLong )
3013 const QVariantList list = attrValue.toList();
3014 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3016 const int count = list.count();
3017 long long *lst =
new long long[count];
3021 for (
const QVariant &value : list )
3023 lst[pos] = value.toLongLong();
3027 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3032 QStringList strings;
3033 strings.reserve( list.size() );
3034 for (
const QVariant &value : list )
3036 strings << QString::number( value.toLongLong() );
3038 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3045 case QMetaType::Type::QVariantMap:
3048 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3049 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3051 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3053 if ( !doc.isNull() )
3055 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3056 jsonString = QString::fromUtf8( json.data() );
3058 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3068 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
3071 .arg( attrValue.typeName(),
3072 attrValue.toString() );
3085 if ( mCoordinateTransform )
3090 geom.
transform( *mCoordinateTransform );
3108 OGRGeometryH mGeom2 =
nullptr;
3137 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3144 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3164 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3165 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3175 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3176 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3177 if ( err != OGRERR_NONE )
3179 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3180 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3187 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3195 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3197 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3198 if ( err != OGRERR_NONE )
3200 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3201 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3208 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3223 for (
int i = 0; i < attributes.size(); i++ )
3225 if ( omap.find( i ) != omap.end() )
3230bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3232 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3234 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3244 if ( mUsingTransaction )
3246 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3248 QgsDebugError( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3261 const QString &fileName,
3262 const QString &fileEncoding,
3264 const QString &driverName,
3266 QString *errorMessage,
3267 const QStringList &datasourceOptions,
3268 const QStringList &layerOptions,
3269 bool skipAttributeCreation,
3270 QString *newFilename,
3272 double symbologyScale,
3282 if ( destCRS.
isValid() && layer )
3308 const QString &fileName,
3309 const QString &fileEncoding,
3311 const QString &driverName,
3313 QString *errorMessage,
3314 const QStringList &datasourceOptions,
3315 const QStringList &layerOptions,
3316 bool skipAttributeCreation,
3317 QString *newFilename,
3319 double symbologyScale,
3350 : driverName( QStringLiteral(
"GPKG" ) )
3358 if ( !layer || !layer->
isValid() )
3365 details.sourceCrs = layer->
crs();
3366 details.sourceWkbType = layer->
wkbType();
3367 details.sourceFields = layer->
fields();
3376 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3384 details.geometryTypeScanIterator = layer->
getFeatures( req );
3388 details.renderContext.setExpressionContext( details.expressionContext );
3389 details.renderContext.setRendererScale( options.
symbologyScale );
3391 details.shallTransform =
false;
3396 details.shallTransform =
true;
3401 details.outputCrs = details.sourceCrs;
3404 details.destWkbType = details.sourceWkbType;
3418 details.attributes.clear();
3419 else if ( details.attributes.isEmpty() )
3421 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3422 for (
int idx : allAttributes )
3424 QgsField fld = details.sourceFields.at( idx );
3425 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3427 details.attributes.append( idx );
3431 if ( !details.attributes.isEmpty() )
3433 for (
int attrIdx : std::as_const( details.attributes ) )
3435 if ( details.sourceFields.exists( attrIdx ) )
3437 QgsField field = details.sourceFields.at( attrIdx );
3439 details.outputFields.append( field );
3443 QgsDebugError( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3450 if ( details.providerType == QLatin1String(
"spatialite" ) )
3452 for (
int i = 0; i < details.outputFields.size(); i++ )
3454 if ( details.outputFields.at( i ).type() == QMetaType::Type::LongLong )
3459 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3461 details.outputFields[i].setType( QMetaType::Type::Int );
3469 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3479 bool useFilterRect =
true;
3480 if ( details.shallTransform )
3491 useFilterRect =
false;
3494 if ( useFilterRect )
3500 details.filterRectEngine->prepareGeometry();
3502 details.sourceFeatureIterator = layer->
getFeatures( req );
3521 int lastProgressReport = 0;
3522 long long total = details.featureCount;
3525 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3527 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3528 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3532 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3533 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3534 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3535 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3538 *
errorMessage = QObject::tr(
"Cannot overwrite an OGR layer in place" );
3558 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3559 if ( newProgress != lastProgressReport )
3561 lastProgressReport = newProgress;
3576 QString tempNewFilename;
3577 QString tempNewLayer;
3585 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
3589 *newFilename = tempNewFilename;
3592 *newLayer = tempNewLayer;
3621 switch ( writer->symbologyExport() )
3639 int n = 0, errors = 0;
3648 writer->startRender( details.renderer.get(), details.sourceFields );
3650 writer->resetMap( details.attributes );
3652 writer->mFields = details.sourceFields;
3656 int initialProgress = lastProgressReport;
3657 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3668 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3669 if ( newProgress < 100 && newProgress != lastProgressReport )
3671 lastProgressReport = newProgress;
3676 if ( details.shallTransform )
3689 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
3690 .arg( fet.
id() ).arg( e.
what() );
3707 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3714 *
errorMessage = QObject::tr(
"Feature write errors:" );
3720 if ( errors > 1000 )
3724 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3734 writer->stopRender();
3738 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3743 bool metadataFailure =
false;
3748 {QStringLiteral(
"path" ), tempNewFilename },
3749 {QStringLiteral(
"layerName" ), tempNewLayer }
3763 metadataFailure =
true;
3774 metadataFailure =
true;
3782 const QString &fileName,
3784 QString *newFilename,
3788 QgsVectorFileWriter::PreparedWriterDetails details;
3789 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3797 const QString &fileName,
3800 QString *newFilename,
3804 QgsVectorFileWriter::PreparedWriterDetails details;
3805 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3814 QgsVectorFileWriter::PreparedWriterDetails details;
3815 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3824 QFileInfo fi( fileName );
3825 QDir dir = fi.dir();
3828 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3830 filter << fi.completeBaseName() + suffix;
3834 const auto constEntryList = dir.entryList( filter );
3835 for (
const QString &file : constEntryList )
3837 QFile f( dir.canonicalPath() +
'/' + file );
3840 QgsDebugError( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3856 QStringList driverNames;
3859 for (
int i = 0; i < GDALGetDriverCount(); ++i )
3861 GDALDriverH
driver = GDALGetDriver( i );
3868 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
3869 if ( driverExtensions.isEmpty() )
3872 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
3873 if ( splitExtensions.intersects( multiLayerExtensions ) )
3875 driverNames << GDALGetDescription(
driver );
3883 static QReadWriteLock sFilterLock;
3884 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3888 const auto it = sFilters.constFind( options );
3889 if ( it != sFilters.constEnd() )
3893 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3896 int const drvCount = OGRGetDriverCount();
3900 for (
int i = 0; i < drvCount; ++i )
3902 OGRSFDriverH drv = OGRGetDriver( i );
3905 const QString drvName = GDALGetDescription( drv );
3909 if ( !multiLayerDrivers.contains( drvName ) )
3913 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3914 bool nonSpatialFormat =
false;
3917 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr );
3920 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3925 if ( nonSpatialFormat )
3930 if ( filterString.isEmpty() )
3937 globs = metadata.
glob.toLower().split(
' ' );
3943 details.
globs = globs;
3952 if ( options & SortRecommended )
3954 if ( a.driverName == QLatin1String(
"GPKG" ) )
3956 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3958 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3960 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
3967 sFilters.insert( options, results );
3974 QSet< QString > extensions;
3976 const thread_local QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
3980 for (
const QString &glob : format.globs )
3982 const QRegularExpressionMatch match = rx.match( glob );
3983 if ( !match.hasMatch() )
3986 const QString matched = match.captured( 1 );
3987 extensions.insert( matched );
3991 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
3993 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
3995 if ( options & SortRecommended )
3997 if ( a == QLatin1String(
"gpkg" ) )
3999 else if ( b == QLatin1String(
"gpkg" ) )
4001 else if ( a == QLatin1String(
"shp" ) )
4003 else if ( b == QLatin1String(
"shp" ) )
4007 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4010 return extensionList;
4015 QList< QgsVectorFileWriter::DriverDetails > results;
4018 const int drvCount = OGRGetDriverCount();
4022 QStringList writableDrivers;
4023 for (
int i = 0; i < drvCount; ++i )
4025 OGRSFDriverH drv = OGRGetDriver( i );
4028 const QString drvName = GDALGetDescription( drv );
4032 if ( !multiLayerDrivers.contains( drvName ) )
4040 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
4044 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
4046 writableDrivers << QStringLiteral(
"DBF file" );
4048 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4051 if ( drvName == QLatin1String(
"MapInfo File" ) )
4053 writableDrivers << QStringLiteral(
"MapInfo MIF" );
4055 else if ( drvName == QLatin1String(
"SQLite" ) )
4062 QString option = QStringLiteral(
"SPATIALITE=YES" );
4063 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4064 OGRSFDriverH poDriver;
4066 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4069 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
4072 writableDrivers << QStringLiteral(
"SpatiaLite" );
4073 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
4076 CPLFree( options[0] );
4078 writableDrivers << drvName;
4083 results.reserve( writableDrivers.count() );
4084 for (
const QString &drvName : std::as_const( writableDrivers ) )
4098 if ( options & SortRecommended )
4100 if ( a.driverName == QLatin1String(
"GPKG" ) )
4102 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4104 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4106 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4110 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4117 QString ext = extension.trimmed();
4118 if ( ext.isEmpty() )
4121 if ( ext.startsWith(
'.' ) )
4125 int const drvCount = GDALGetDriverCount();
4127 for (
int i = 0; i < drvCount; ++i )
4129 GDALDriverH drv = GDALGetDriver( i );
4135 QString drvName = GDALGetDriverShortName( drv );
4136 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4138 const auto constDriverExtensions = driverExtensions;
4139 for (
const QString &
driver : constDriverExtensions )
4141 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4152 QString filterString;
4156 if ( !filterString.isEmpty() )
4157 filterString += QLatin1String(
";;" );
4159 filterString += details.filterString;
4161 return filterString;
4170 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4171 metadata.
glob.toLower(),
4172 metadata.
glob.toUpper() );
4177 if ( codecName == QLatin1String(
"System" ) )
4178 return QStringLiteral(
"LDID/0" );
4180 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4181 const QRegularExpressionMatch match = re.match( codecName );
4182 if ( match.hasMatch() )
4184 QString
c = match.captured( 2 ).remove(
'-' );
4186 ( void )
c.toInt( &isNumber );
4214 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4215 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4218 int nTotalLevels = 0;
4220 QgsSymbolList::iterator symbolIt = symbolList.begin();
4221 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4223 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4224 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4226 int nLevels = ( *symbolIt )->symbolLayerCount();
4227 for (
int i = 0; i < nLevels; ++i )
4229 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4230 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4231 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4235 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4241 if ( !details.renderer )
4246 QHash< QgsSymbol *, QList<QgsFeature> > features;
4255 startRender( details.renderer.get(), details.sourceFields );
4275 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4286 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4287 if ( !featureSymbol )
4292 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4293 if ( it == features.end() )
4295 it = features.insert( featureSymbol, QList<QgsFeature>() );
4297 it.value().append( fet );
4302 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4303 for (
int i = 0; i < symbols.count(); i++ )
4309 if ( level < 0 || level >= 1000 )
4312 while ( level >= levels.count() )
4314 levels[level].append( item );
4319 int nTotalFeatures = 0;
4322 for (
int l = 0; l < levels.count(); l++ )
4325 for (
int i = 0; i < level.count(); i++ )
4328 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4329 if ( levelIt == features.end() )
4335 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4336 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4338 int llayer = item.
layer();
4339 QList<QgsFeature> &featureList = levelIt.value();
4340 QList<QgsFeature>::iterator featureIt = featureList.begin();
4341 for ( ; featureIt != featureList.end(); ++featureIt )
4351 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4352 if ( !styleString.isEmpty() )
4354 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4355 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4368 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4385 return 1000 / scale;
4402 return scale / 1000;
4410 mRenderer = createSymbologyRenderer( sourceRenderer );
4416 mRenderer->startRender( mRenderContext, fields );
4419void QgsVectorFileWriter::stopRender()
4426 mRenderer->stopRender( mRenderContext );
4429std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4442 if ( !sourceRenderer )
4447 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4454 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4455 for (
const QString &attr : rendererAttributes )
4460 attList.append( index );
4466QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4469 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4471 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4474 switch ( option->
type )
4481 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4491 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4501 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4508 if ( opt && !opt->
mValue.isEmpty() )
4510 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4521 OGRSFDriverH hDriver =
nullptr;
4525 const QString drvName = GDALGetDescription( hDriver );
4527 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4532 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4535 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4539 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4542 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4545 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4548 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4559 const QString &layerNameIn )
4561 OGRSFDriverH hDriver =
nullptr;
4566 QString layerName( layerNameIn );
4567 if ( layerName.isEmpty() )
4568 layerName = QFileInfo( datasetName ).baseName();
4570 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4575 const QString &layerName,
4579 OGRSFDriverH hDriver =
nullptr;
4583 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4589 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4590 const auto constAttributes = attributes;
4591 for (
int idx : constAttributes )
4594 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.