37 #include "qgsogrproviderutils.h" 
   47 #include <QTextStream> 
   51 #include <QRegularExpression> 
   52 #include <QJsonDocument> 
   58 #include <ogr_srs_api.h> 
   59 #include <cpl_error.h> 
   61 #include <cpl_string.h> 
   80   const QString &vectorFileName,
 
   81   const QString &fileEncoding,
 
   85   const QString &driverName,
 
   86   const QStringList &datasourceOptions,
 
   87   const QStringList &layerOptions,
 
   90   QgsFeatureSink::SinkFlags sinkFlags,
 
  100   init( vectorFileName, fileEncoding, fields,  geometryType,
 
  101         srs, driverName, datasourceOptions, layerOptions, newFilename, 
nullptr,
 
  106   const QString &vectorFileName,
 
  107   const QString &fileEncoding,
 
  111   const QString &driverName,
 
  112   const QStringList &datasourceOptions,
 
  113   const QStringList &layerOptions,
 
  114   QString *newFilename,
 
  117   const QString &layerName,
 
  121   QgsFeatureSink::SinkFlags sinkFlags,
 
  125   , mWkbType( geometryType )
 
  126   , mSymbologyExport( symbologyExport )
 
  127   , mSymbologyScale( 1.0 )
 
  129   init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
 
  130         datasourceOptions, layerOptions, newFilename, fieldValueConverter,
 
  131         layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource );
 
  135   const QString &fileName,
 
  141   QgsFeatureSink::SinkFlags sinkFlags,
 
  142   QString *newFilename,
 
  156   if ( driverName == QLatin1String( 
"MapInfo MIF" ) )
 
  160   GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
 
  168   return CSLFetchBoolean( 
driverMetadata, GDAL_DCAP_FEATURE_STYLES, 
false );
 
  171 void QgsVectorFileWriter::init( QString vectorFileName,
 
  172                                 QString fileEncoding,
 
  176                                 const QString &driverName,
 
  177                                 QStringList datasourceOptions,
 
  178                                 QStringList layerOptions,
 
  179                                 QString *newFilename,
 
  180                                 FieldValueConverter *fieldValueConverter,
 
  181                                 const QString &layerNameIn,
 
  182                                 ActionOnExistingFile action,
 
  183                                 QString *newLayer, SinkFlags sinkFlags,
 
  188   if ( vectorFileName.isEmpty() )
 
  195   if ( driverName == QLatin1String( 
"MapInfo MIF" ) )
 
  199   else if ( driverName == QLatin1String( 
"SpatiaLite" ) )
 
  202     if ( !datasourceOptions.contains( QStringLiteral( 
"SPATIALITE=YES" ) ) )
 
  204       datasourceOptions.append( QStringLiteral( 
"SPATIALITE=YES" ) );
 
  207   else if ( driverName == QLatin1String( 
"DBF file" ) )
 
  210     if ( !layerOptions.contains( QStringLiteral( 
"SHPT=NULL" ) ) )
 
  212       layerOptions.append( QStringLiteral( 
"SHPT=NULL" ) );
 
  221 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1) 
  222   QString fidFieldName;
 
  225     for ( 
const QString &layerOption : layerOptions )
 
  227       if ( layerOption.startsWith( QLatin1String( 
"FID=" ) ) )
 
  229         fidFieldName = layerOption.mid( 4 );
 
  233     if ( fidFieldName.isEmpty() )
 
  234       fidFieldName = QStringLiteral( 
"fid" );
 
  239   OGRSFDriverH poDriver;
 
  242   poDriver = OGRGetDriverByName( 
mOgrDriverName.toLocal8Bit().constData() );
 
  246     mErrorMessage = QObject::tr( 
"OGR driver for '%1' not found (OGR error: %2)" )
 
  248                           QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  258     if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String( 
"ENCODING=" ) ) == -1 )
 
  263     if ( driverName == QLatin1String( 
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String( 
".shp" ), Qt::CaseInsensitive ) )
 
  265       vectorFileName += QLatin1String( 
".shp" );
 
  267     else if ( driverName == QLatin1String( 
"DBF file" ) && !vectorFileName.endsWith( QLatin1String( 
".dbf" ), Qt::CaseInsensitive ) )
 
  269       vectorFileName += QLatin1String( 
".dbf" );
 
  279 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) 
  280       QStringList allExts = metadata.ext.split( 
' ', QString::SkipEmptyParts );
 
  282       QStringList allExts = metadata.ext.split( 
' ', Qt::SkipEmptyParts );
 
  285       const auto constAllExts = allExts;
 
  286       for ( 
const QString &ext : constAllExts )
 
  288         if ( vectorFileName.endsWith( 
'.' + ext, Qt::CaseInsensitive ) )
 
  297         vectorFileName += 
'.' + allExts[0];
 
  303       if ( vectorFileName.endsWith( QLatin1String( 
".gdb" ), Qt::CaseInsensitive ) )
 
  305         QDir dir( vectorFileName );
 
  308           QFileInfoList fileList = dir.entryInfoList(
 
  309                                      QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
 
  310           const auto constFileList = fileList;
 
  311           for ( 
const QFileInfo &info : constFileList )
 
  313             QFile::remove( info.absoluteFilePath() );
 
  316         QDir().rmdir( vectorFileName );
 
  320         QFile::remove( vectorFileName );
 
  325   if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
 
  327     if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
 
  329       QgsDebugMsgLevel( QStringLiteral( 
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
 
  330       fileEncoding = metadata.compulsoryEncoding;
 
  335   char **options = 
nullptr;
 
  336   if ( !datasourceOptions.isEmpty() )
 
  338     options = 
new char *[ datasourceOptions.size() + 1 ];
 
  339     for ( 
int i = 0; i < datasourceOptions.size(); i++ )
 
  341       QgsDebugMsgLevel( QStringLiteral( 
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
 
  342       options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().constData() );
 
  344     options[ datasourceOptions.size()] = 
nullptr;
 
  350     mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
 
  352     mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE, 
nullptr ) );
 
  356     for ( 
int i = 0; i < datasourceOptions.size(); i++ )
 
  357       CPLFree( options[i] );
 
  366       mErrorMessage = QObject::tr( 
"Creation of data source failed (OGR error: %1)" )
 
  367                       .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  369       mErrorMessage = QObject::tr( 
"Opening of data source in update mode failed (OGR error: %1)" )
 
  370                       .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  374   QString layerName( layerNameIn );
 
  375   if ( layerName.isEmpty() )
 
  376     layerName = QFileInfo( vectorFileName ).baseName();
 
  380     const int layer_count = OGR_DS_GetLayerCount( 
mDS.get() );
 
  381     for ( 
int i = 0; i < layer_count; i++ )
 
  383       OGRLayerH hLayer = OGR_DS_GetLayer( 
mDS.get(), i );
 
  384       if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
 
  386         if ( OGR_DS_DeleteLayer( 
mDS.get(), i ) != OGRERR_NONE )
 
  389           mErrorMessage = QObject::tr( 
"Overwriting of existing layer failed (OGR error: %1)" )
 
  390                           .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  404     QgsDebugMsgLevel( QStringLiteral( 
"Opened data source in update mode" ), 2 );
 
  408   mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
 
  411     QgsDebugMsg( 
"error finding QTextCodec for " + fileEncoding );
 
  414     QString enc = settings.
value( QStringLiteral( 
"UI/encoding" ), 
"System" ).toString();
 
  415     mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
 
  418       QgsDebugMsg( 
"error finding QTextCodec for " + enc );
 
  419       mCodec = QTextCodec::codecForLocale();
 
  425   if ( driverName == QLatin1String( 
"KML" ) || driverName == QLatin1String( 
"LIBKML" ) || driverName == QLatin1String( 
"GPX" ) )
 
  427     if ( srs.
authid() != QLatin1String( 
"EPSG:4326" ) )
 
  442   int optIndex = layerOptions.indexOf( QLatin1String( 
"FEATURE_DATASET=" ) );
 
  443   if ( optIndex != -1 )
 
  445     layerOptions.removeAt( optIndex );
 
  448   if ( !layerOptions.isEmpty() )
 
  450     options = 
new char *[ layerOptions.size() + 1 ];
 
  451     for ( 
int i = 0; i < layerOptions.size(); i++ )
 
  454       options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().constData() );
 
  456     options[ layerOptions.size()] = 
nullptr;
 
  460   CPLSetConfigOption( 
"SHAPE_ENCODING", 
"" );
 
  464     mLayer = OGR_DS_CreateLayer( 
mDS.get(), layerName.toUtf8().constData(), 
mOgrRef, wkbType, options );
 
  467       *newLayer = OGR_L_GetName( 
mLayer );
 
  468       if ( driverName == QLatin1String( 
"GPX" ) )
 
  475             if ( !EQUAL( layerName.toUtf8().constData(), 
"track_points" ) &&
 
  476                  !EQUAL( layerName.toUtf8().constData(), 
"route_points" ) )
 
  478               *newLayer = QStringLiteral( 
"waypoints" );
 
  485             const char *pszForceGPXTrack
 
  486               = CSLFetchNameValue( options, 
"FORCE_GPX_TRACK" );
 
  487             if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
 
  488               *newLayer = QStringLiteral( 
"tracks" );
 
  490               *newLayer = QStringLiteral( 
"routes" );
 
  497             const char *pszForceGPXRoute
 
  498               = CSLFetchNameValue( options, 
"FORCE_GPX_ROUTE" );
 
  499             if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
 
  500               *newLayer = QStringLiteral( 
"routes" );
 
  502               *newLayer = QStringLiteral( 
"tracks" );
 
  512   else if ( driverName == QLatin1String( 
"DGN" ) )
 
  514     mLayer = OGR_DS_GetLayerByName( 
mDS.get(), 
"elements" );
 
  518     mLayer = OGR_DS_GetLayerByName( 
mDS.get(), layerName.toUtf8().constData() );
 
  523     for ( 
int i = 0; i < layerOptions.size(); i++ )
 
  524       CPLFree( options[i] );
 
  533       QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String( 
".shp" ), Qt::CaseInsensitive ) );
 
  534       QFile prjFile( layerName + 
".qpj" );
 
  535       if ( prjFile.exists() )
 
  543       mErrorMessage = QObject::tr( 
"Creation of layer failed (OGR error: %1)" )
 
  544                       .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  546       mErrorMessage = QObject::tr( 
"Opening of layer failed (OGR error: %1)" )
 
  547                       .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  552   OGRFeatureDefnH defn = OGR_L_GetLayerDefn( 
mLayer );
 
  561   QSet<int> existingIdxs;
 
  571       for ( 
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
 
  575         if ( fieldValueConverter )
 
  577           attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
 
  582           int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( attrField.
name() ) );
 
  591         switch ( fieldNameSource )
 
  594             name = attrField.
name();
 
  598             name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
 
  602         OGRFieldType ogrType = OFTString; 
 
  603         OGRFieldSubType ogrSubType = OFSTNone;
 
  604         int ogrWidth = attrField.
length();
 
  605         int ogrPrecision = attrField.
precision();
 
  606         if ( ogrPrecision > 0 )
 
  609         switch ( attrField.
type() )
 
  611           case QVariant::LongLong:
 
  613             const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  614             if ( pszDataTypes && strstr( pszDataTypes, 
"Integer64" ) )
 
  615               ogrType = OFTInteger64;
 
  618             ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
 
  622           case QVariant::String:
 
  624             if ( ( ogrWidth <= 0 || ogrWidth > 255 ) && 
mOgrDriverName == QLatin1String( 
"ESRI Shapefile" ) )
 
  629             ogrType = OFTInteger;
 
  630             ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
 
  635             ogrType = OFTInteger;
 
  636             ogrSubType = OFSTBoolean;
 
  641           case QVariant::Double:
 
  642 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1) 
  643             if ( 
mOgrDriverName == QLatin1String( 
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
 
  646               ogrType = OFTInteger64;
 
  669           case QVariant::DateTime:
 
  677               ogrType = OFTDateTime;
 
  681           case QVariant::ByteArray:
 
  685           case QVariant::StringList:
 
  691               ogrSubType = OFSTJSON;
 
  695             const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  696             if ( pszDataTypes && strstr( pszDataTypes, 
"StringList" ) )
 
  698               ogrType = OFTStringList;
 
  699               mSupportedListSubTypes.insert( QVariant::String );
 
  714               ogrSubType = OFSTJSON;
 
  719             if ( attrField.
subType() == QVariant::String )
 
  721               const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  722               if ( pszDataTypes && strstr( pszDataTypes, 
"StringList" ) )
 
  724                 ogrType = OFTStringList;
 
  725                 mSupportedListSubTypes.insert( QVariant::String );
 
  734             else if ( attrField.
subType() == QVariant::Int )
 
  736               const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  737               if ( pszDataTypes && strstr( pszDataTypes, 
"IntegerList" ) )
 
  739                 ogrType = OFTIntegerList;
 
  740                 mSupportedListSubTypes.insert( QVariant::Int );
 
  749             else if ( attrField.
subType() == QVariant::Double )
 
  751               const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  752               if ( pszDataTypes && strstr( pszDataTypes, 
"RealList" ) )
 
  754                 ogrType = OFTRealList;
 
  755                 mSupportedListSubTypes.insert( QVariant::Double );
 
  764             else if ( attrField.
subType() == QVariant::LongLong )
 
  766               const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  767               if ( pszDataTypes && strstr( pszDataTypes, 
"Integer64List" ) )
 
  769                 ogrType = OFTInteger64List;
 
  770                 mSupportedListSubTypes.insert( QVariant::LongLong );
 
  784             mErrorMessage = QObject::tr( 
"Unsupported type for field %1" )
 
  785                             .arg( attrField.
name() );
 
  790         if ( 
mOgrDriverName == QLatin1String( 
"SQLite" ) && name.compare( QLatin1String( 
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
 
  793           for ( i = 0; i < 10; i++ )
 
  795             name = QStringLiteral( 
"ogc_fid%1" ).arg( i );
 
  798             for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
 
  801             if ( j == fields.
size() )
 
  807             mErrorMessage = QObject::tr( 
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
 
  812           QgsMessageLog::logMessage( QObject::tr( 
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr( 
"OGR" ) );
 
  819           OGR_Fld_SetWidth( fld.get(), ogrWidth );
 
  822         if ( ogrPrecision >= 0 )
 
  824           OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
 
  827         if ( ogrSubType != OFSTNone )
 
  828           OGR_Fld_SetSubType( fld.get(), ogrSubType );
 
  832                           " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
 
  833                           " width " + QString::number( ogrWidth ) +
 
  834                           " precision " + QString::number( ogrPrecision ), 2 );
 
  835         if ( OGR_L_CreateField( 
mLayer, fld.get(), 
true ) != OGRERR_NONE )
 
  838           mErrorMessage = QObject::tr( 
"Creation of field %1 failed (OGR error: %2)" )
 
  839                           .arg( attrField.
name(),
 
  840                                 QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  845         int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( name ) );
 
  846         QgsDebugMsgLevel( QStringLiteral( 
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
 
  847         if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
 
  850           ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
 
  855             mErrorMessage = QObject::tr( 
"Created field %1 not found (OGR error: %2)" )
 
  856                             .arg( attrField.
name(),
 
  857                                   QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  863         existingIdxs.insert( ogrIdx );
 
  871       for ( 
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
 
  874         QString name( attrField.
name() );
 
  875         int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( name ) );
 
  887     int fidIdx = fields.
lookupField( QStringLiteral( 
"FID" ) );
 
  898     *newFilename = vectorFileName;
 
  901   mUsingTransaction = 
true;
 
  902   if ( OGRERR_NONE != OGR_L_StartTransaction( 
mLayer ) )
 
  904     mUsingTransaction = 
false;
 
  914 class QgsVectorFileWriterMetadataContainer
 
  918     QgsVectorFileWriterMetadataContainer()
 
  920       QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
 
  921       QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
 
  924       datasetOptions.clear();
 
  925       layerOptions.clear();
 
  927       driverMetadata.insert( QStringLiteral( 
"AVCE00" ),
 
  929                                QStringLiteral( 
"Arc/Info ASCII Coverage" ),
 
  930                                QObject::tr( 
"Arc/Info ASCII Coverage" ),
 
  931                                QStringLiteral( 
"*.e00" ),
 
  932                                QStringLiteral( 
"e00" ),
 
  939 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0) 
  943       datasetOptions.clear();
 
  944       layerOptions.clear();
 
  947                                QObject::tr( 
"New BNA files are created by the " 
  948                                             "systems default line termination conventions. " 
  949                                             "This may be overridden here." ),
 
  951                                << QStringLiteral( 
"CRLF" )
 
  952                                << QStringLiteral( 
"LF" ),
 
  958                                QObject::tr( 
"By default, BNA files are created in multi-line format. " 
  959                                             "For each record, the first line contains the identifiers and the " 
  960                                             "type/number of coordinates to follow. Each following line contains " 
  961                                             "a pair of coordinates." ),
 
  966                                QObject::tr( 
"BNA records may contain from 2 to 4 identifiers per record. " 
  967                                             "Some software packages only support a precise number of identifiers. " 
  968                                             "You can override the default value (2) by a precise value." ),
 
  970                                << QStringLiteral( 
"2" )
 
  971                                << QStringLiteral( 
"3" )
 
  972                                << QStringLiteral( 
"4" )
 
  973                                << QStringLiteral( 
"NB_SOURCE_FIELDS" ),
 
  974                                QStringLiteral( 
"2" ) 
 
  978                                QObject::tr( 
"The BNA writer will try to recognize ellipses and circles when writing a polygon. " 
  979                                             "This will only work if the feature has previously been read from a BNA file. " 
  980                                             "As some software packages do not support ellipses/circles in BNA data file, " 
  981                                             "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not " 
  982                                             "to export them as such, but keep them as polygons." ),
 
  987                                QObject::tr( 
"Limit the number of coordinate pairs per line in multiline format." ),
 
  992                                QObject::tr( 
"Set the number of decimal for coordinates. Default value is 10." ),
 
  996       driverMetadata.insert( QStringLiteral( 
"BNA" ),
 
  998                                QStringLiteral( 
"Atlas BNA" ),
 
  999                                QObject::tr( 
"Atlas BNA" ),
 
 1000                                QStringLiteral( 
"*.bna" ),
 
 1001                                QStringLiteral( 
"bna" ),
 
 1009       datasetOptions.clear();
 
 1010       layerOptions.clear();
 
 1013                              QObject::tr( 
"By default when creating new .csv files they " 
 1014                                           "are created with the line termination conventions " 
 1015                                           "of the local platform (CR/LF on Win32 or LF on all other systems). " 
 1016                                           "This may be overridden through the use of the LINEFORMAT option." ),
 
 1018                              << QStringLiteral( 
"CRLF" )
 
 1019                              << QStringLiteral( 
"LF" ),
 
 1025                              QObject::tr( 
"By default, the geometry of a feature written to a .csv file is discarded. " 
 1026                                           "It is possible to export the geometry in its WKT representation by " 
 1027                                           "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries " 
 1028                                           "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY " 
 1029                                           "or GEOMETRY=AS_YX." ),
 
 1031                              << QStringLiteral( 
"AS_WKT" )
 
 1032                              << QStringLiteral( 
"AS_XYZ" )
 
 1033                              << QStringLiteral( 
"AS_XY" )
 
 1034                              << QStringLiteral( 
"AS_YX" ),
 
 1040                              QObject::tr( 
"Create the associated .csvt file to describe the type of each " 
 1041                                           "column of the layer and its optional width and precision." ),
 
 1046                              QObject::tr( 
"Field separator character." ),
 
 1048                              << QStringLiteral( 
"COMMA" )
 
 1049                              << QStringLiteral( 
"SEMICOLON" )
 
 1050                              << QStringLiteral( 
"TAB" ),
 
 1051                              QStringLiteral( 
"COMMA" ) 
 
 1055                              QObject::tr( 
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
 
 1057                              << QStringLiteral( 
"IF_NEEDED" )
 
 1058                              << QStringLiteral( 
"IF_AMBIGUOUS" )
 
 1059                              << QStringLiteral( 
"ALWAYS" ),
 
 1060                              QStringLiteral( 
"IF_AMBIGUOUS" ) 
 
 1064                              QObject::tr( 
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
 
 1068       driverMetadata.insert( QStringLiteral( 
"CSV" ),
 
 1070                                QStringLiteral( 
"Comma Separated Value [CSV]" ),
 
 1071                                QObject::tr( 
"Comma Separated Value [CSV]" ),
 
 1072                                QStringLiteral( 
"*.csv" ),
 
 1073                                QStringLiteral( 
"csv" ),
 
 1079 #if defined(GDAL_COMPUTE_VERSION) && GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) 
 1081       datasetOptions.clear();
 
 1082       layerOptions.clear();
 
 1084       driverMetadata.insert( QStringLiteral( 
"FlatGeobuf" ),
 
 1086                                QStringLiteral( 
"FlatGeobuf" ),
 
 1087                                QObject::tr( 
"FlatGeobuf" ),
 
 1088                                QStringLiteral( 
"*.fgb" ),
 
 1089                                QStringLiteral( 
"fgb" ),
 
 1092                                QStringLiteral( 
"UTF-8" )
 
 1098       datasetOptions.clear();
 
 1099       layerOptions.clear();
 
 1102                              QObject::tr( 
"Override the type of shapefile created. " 
 1103                                           "Can be one of NULL for a simple .dbf file with no .shp file, POINT, " 
 1104                                           "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or " 
 1105                                           "MULTIPOINTZ for 3D;" ) +
 
 1106                              QObject::tr( 
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries" 
 1107                                           " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured" 
 1109                              QObject::tr( 
" MULTIPATCH files are supported since GDAL 2.2." ) +
 
 1112                              << QStringLiteral( 
"NULL" )
 
 1113                              << QStringLiteral( 
"POINT" )
 
 1114                              << QStringLiteral( 
"ARC" )
 
 1115                              << QStringLiteral( 
"POLYGON" )
 
 1116                              << QStringLiteral( 
"MULTIPOINT" )
 
 1117                              << QStringLiteral( 
"POINTZ" )
 
 1118                              << QStringLiteral( 
"ARCZ" )
 
 1119                              << QStringLiteral( 
"POLYGONZ" )
 
 1120                              << QStringLiteral( 
"MULTIPOINTZ" )
 
 1121                              << QStringLiteral( 
"POINTM" )
 
 1122                              << QStringLiteral( 
"ARCM" )
 
 1123                              << QStringLiteral( 
"POLYGONM" )
 
 1124                              << QStringLiteral( 
"MULTIPOINTM" )
 
 1125                              << QStringLiteral( 
"POINTZM" )
 
 1126                              << QStringLiteral( 
"ARCZM" )
 
 1127                              << QStringLiteral( 
"POLYGONZM" )
 
 1128                              << QStringLiteral( 
"MULTIPOINTZM" )
 
 1129                              << QStringLiteral( 
"MULTIPATCH" )
 
 1139                              QObject::tr( 
"Set the encoding value in the DBF file. " 
 1140                                           "The default value is LDID/87. It is not clear " 
 1141                                           "what other values may be appropriate." ),
 
 1149                              QObject::tr( 
"Set to YES to resize fields to their optimal size." ),
 
 1153       driverMetadata.insert( QStringLiteral( 
"ESRI" ),
 
 1155                                QStringLiteral( 
"ESRI Shapefile" ),
 
 1156                                QObject::tr( 
"ESRI Shapefile" ),
 
 1157                                QStringLiteral( 
"*.shp" ),
 
 1158                                QStringLiteral( 
"shp" ),
 
 1165       datasetOptions.clear();
 
 1166       layerOptions.clear();
 
 1168       driverMetadata.insert( QStringLiteral( 
"DBF File" ),
 
 1170                                QStringLiteral( 
"DBF File" ),
 
 1171                                QObject::tr( 
"DBF File" ),
 
 1172                                QStringLiteral( 
"*.dbf" ),
 
 1173                                QStringLiteral( 
"dbf" ),
 
 1180       datasetOptions.clear();
 
 1181       layerOptions.clear();
 
 1183       driverMetadata.insert( QStringLiteral( 
"FMEObjects Gateway" ),
 
 1185                                QStringLiteral( 
"FMEObjects Gateway" ),
 
 1186                                QObject::tr( 
"FMEObjects Gateway" ),
 
 1187                                QStringLiteral( 
"*.fdd" ),
 
 1188                                QStringLiteral( 
"fdd" ),
 
 1195       datasetOptions.clear();
 
 1196       layerOptions.clear();
 
 1199                              QObject::tr( 
"Set to YES to write a bbox property with the bounding box " 
 1200                                           "of the geometries at the feature and feature collection level." ),
 
 1205                              QObject::tr( 
"Maximum number of figures after decimal separator to write in coordinates. " 
 1206                                           "Defaults to 15. Truncation will occur to remove trailing zeros." ),
 
 1211                              QObject::tr( 
"Whether to use RFC 7946 standard. " 
 1212                                           "If disabled GeoJSON 2008 initial version will be used. " 
 1213                                           "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
 
 1217       driverMetadata.insert( QStringLiteral( 
"GeoJSON" ),
 
 1219                                QStringLiteral( 
"GeoJSON" ),
 
 1220                                QObject::tr( 
"GeoJSON" ),
 
 1221                                QStringLiteral( 
"*.geojson" ),
 
 1222                                QStringLiteral( 
"geojson" ),
 
 1225                                QStringLiteral( 
"UTF-8" )
 
 1230       datasetOptions.clear();
 
 1231       layerOptions.clear();
 
 1234                              QObject::tr( 
"Maximum number of figures after decimal separator to write in coordinates. " 
 1235                                           "Defaults to 15. Truncation will occur to remove trailing zeros." ),
 
 1240                              QObject::tr( 
"Whether to start records with the RS=0x1E character (RFC 8142 standard). " 
 1241                                           "Defaults to NO: Newline Delimited JSON (geojsonl). \n" 
 1242                                           "If set to YES:  RFC 8142 standard: GeoJSON Text Sequences  (geojsons)." ),
 
 1246       driverMetadata.insert( QStringLiteral( 
"GeoJSONSeq" ),
 
 1248                                QStringLiteral( 
"GeoJSON - Newline Delimited" ),
 
 1249                                QObject::tr( 
"GeoJSON - Newline Delimited" ),
 
 1250                                QStringLiteral( 
"*.geojsonl *.geojsons *.json" ),
 
 1251                                QStringLiteral( 
"json" ),  
 
 1254                                QStringLiteral( 
"UTF-8" )
 
 1259       datasetOptions.clear();
 
 1260       layerOptions.clear();
 
 1263                                QObject::tr( 
"whether the document must be in RSS 2.0 or Atom 1.0 format. " 
 1264                                             "Default value : RSS" ),
 
 1266                                << QStringLiteral( 
"RSS" )
 
 1267                                << QStringLiteral( 
"ATOM" ),
 
 1268                                QStringLiteral( 
"RSS" ) 
 
 1272                                QObject::tr( 
"The encoding of location information. Default value : SIMPLE. " 
 1273                                             "W3C_GEO only supports point geometries. " 
 1274                                             "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
 
 1276                                << QStringLiteral( 
"SIMPLE" )
 
 1277                                << QStringLiteral( 
"GML" )
 
 1278                                << QStringLiteral( 
"W3C_GEO" ),
 
 1279                                QStringLiteral( 
"SIMPLE" ) 
 
 1283                                QObject::tr( 
"If defined to YES, extension fields will be written. " 
 1284                                             "If the field name not found in the base schema matches " 
 1285                                             "the foo_bar pattern, foo will be considered as the namespace " 
 1286                                             "of the element, and a <foo:bar> element will be written. " 
 1287                                             "Otherwise, elements will be written in the <ogr:> namespace." ),
 
 1292                                QObject::tr( 
"If defined to NO, only <entry> or <item> elements will be written. " 
 1293                                             "The user will have to provide the appropriate header and footer of the document." ),
 
 1298                                QObject::tr( 
"XML content that will be put between the <channel> element and the " 
 1299                                             "first <item> element for a RSS document, or between the xml tag and " 
 1300                                             "the first <entry> element for an Atom document." ),
 
 1305                                QObject::tr( 
"Value put inside the <title> element in the header. " 
 1306                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1311                                QObject::tr( 
"Value put inside the <description> element in the header. " 
 1312                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1317                                QObject::tr( 
"Value put inside the <link> element in the header. " 
 1318                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1323                                QObject::tr( 
"Value put inside the <updated> element in the header. " 
 1324                                             "Should be formatted as a XML datetime. " 
 1325                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1330                                QObject::tr( 
"Value put inside the <author><name> element in the header. " 
 1331                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1336                                QObject::tr( 
"Value put inside the <id> element in the header. " 
 1337                                             "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1341       driverMetadata.insert( QStringLiteral( 
"GeoRSS" ),
 
 1343                                QStringLiteral( 
"GeoRSS" ),
 
 1344                                QObject::tr( 
"GeoRSS" ),
 
 1345                                QStringLiteral( 
"*.xml" ),
 
 1346                                QStringLiteral( 
"xml" ),
 
 1349                                QStringLiteral( 
"UTF-8" )
 
 1354       datasetOptions.clear();
 
 1355       layerOptions.clear();
 
 1358                                QObject::tr( 
"If provided, this URI will be inserted as the schema location. " 
 1359                                             "Note that the schema file isn't actually accessed by OGR, so it " 
 1360                                             "is up to the user to ensure it will match the schema of the OGR " 
 1361                                             "produced GML data file." ),
 
 1366                                QObject::tr( 
"This writes a GML application schema file to a corresponding " 
 1367                                             ".xsd file (with the same basename). If INTERNAL is used the " 
 1368                                             "schema is written within the GML file, but this is experimental " 
 1369                                             "and almost certainly not valid XML. " 
 1370                                             "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
 
 1372                                << QStringLiteral( 
"EXTERNAL" )
 
 1373                                << QStringLiteral( 
"INTERNAL" )
 
 1374                                << QStringLiteral( 
"OFF" ),
 
 1375                                QStringLiteral( 
"EXTERNAL" ) 
 
 1379                                QObject::tr( 
"This is the prefix for the application target namespace." ),
 
 1380                                QStringLiteral( 
"ogr" )  
 
 1384                                QObject::tr( 
"Can be set to TRUE to avoid writing the prefix of the " 
 1385                                             "application target namespace in the GML file." ),
 
 1390                                QObject::tr( 
"Defaults to 'http://ogr.maptools.org/'. " 
 1391                                             "This is the application target namespace." ),
 
 1392                                QStringLiteral( 
"http://ogr.maptools.org/" )  
 
 1396                                QObject::tr( 
"If not specified, GML2 will be used." ),
 
 1398                                << QStringLiteral( 
"GML3" )
 
 1399                                << QStringLiteral( 
"GML3Deegree" )
 
 1400                                << QStringLiteral( 
"GML3.2" ),
 
 1406                                QObject::tr( 
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "  
 1407                                             "If YES, SRS with EPSG authority will be written with the " 
 1408                                             "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a " 
 1409                                             "geographic SRS without explicit AXIS order, but that the same " 
 1410                                             "SRS authority code imported with ImportFromEPSGA() should be " 
 1411                                             "treated as lat/long, then the function will take care of coordinate " 
 1412                                             "order swapping. If set to NO, SRS with EPSG authority will be " 
 1413                                             "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
 
 1418                                QObject::tr( 
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. " 
 1419                                             "If set to NO, the <gml:boundedBy> element will not be written for " 
 1425                                QObject::tr( 
"Default to YES. If YES, the output will be indented with spaces " 
 1426                                             "for more readability, but at the expense of file size." ),
 
 1431       driverMetadata.insert( QStringLiteral( 
"GML" ),
 
 1433                                QStringLiteral( 
"Geography Markup Language [GML]" ),
 
 1434                                QObject::tr( 
"Geography Markup Language [GML]" ),
 
 1435                                QStringLiteral( 
"*.gml" ),
 
 1436                                QStringLiteral( 
"gml" ),
 
 1439                                QStringLiteral( 
"UTF-8" )
 
 1444       datasetOptions.clear();
 
 1445       layerOptions.clear();
 
 1448                              QObject::tr( 
"Human-readable identifier (e.g. short name) for the layer content" ),
 
 1453                              QObject::tr( 
"Human-readable description for the layer content" ),
 
 1458                              QObject::tr( 
"Name for the feature identifier column" ),
 
 1459                              QStringLiteral( 
"fid" )  
 
 1463                              QObject::tr( 
"Name for the geometry column" ),
 
 1464                              QStringLiteral( 
"geom" )  
 
 1468                              QObject::tr( 
"If a spatial index must be created." ),
 
 1472       driverMetadata.insert( QStringLiteral( 
"GPKG" ),
 
 1474                                QStringLiteral( 
"GeoPackage" ),
 
 1475                                QObject::tr( 
"GeoPackage" ),
 
 1476                                QStringLiteral( 
"*.gpkg" ),
 
 1477                                QStringLiteral( 
"gpkg" ),
 
 1480                                QStringLiteral( 
"UTF-8" )
 
 1485       datasetOptions.clear();
 
 1486       layerOptions.clear();
 
 1488       driverMetadata.insert( QStringLiteral( 
"GMT" ),
 
 1490                                QStringLiteral( 
"Generic Mapping Tools [GMT]" ),
 
 1491                                QObject::tr( 
"Generic Mapping Tools [GMT]" ),
 
 1492                                QStringLiteral( 
"*.gmt" ),
 
 1493                                QStringLiteral( 
"gmt" ),
 
 1500       datasetOptions.clear();
 
 1501       layerOptions.clear();
 
 1504                              QObject::tr( 
"By default when writing a layer whose features are of " 
 1505                                           "type wkbLineString, the GPX driver chooses to write " 
 1506                                           "them as routes. If FORCE_GPX_TRACK=YES is specified, " 
 1507                                           "they will be written as tracks." ),
 
 1512                              QObject::tr( 
"By default when writing a layer whose features are of " 
 1513                                           "type wkbMultiLineString, the GPX driver chooses to write " 
 1514                                           "them as tracks. If FORCE_GPX_ROUTE=YES is specified, " 
 1515                                           "they will be written as routes, provided that the multilines " 
 1516                                           "are composed of only one single line." ),
 
 1521                                QObject::tr( 
"If GPX_USE_EXTENSIONS=YES is specified, " 
 1522                                             "extra fields will be written inside the <extensions> tag." ),
 
 1527                                QObject::tr( 
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL " 
 1528                                             "is set. The namespace value used for extension tags. By default, 'ogr'." ),
 
 1529                                QStringLiteral( 
"ogr" )  
 
 1533                                QObject::tr( 
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS " 
 1534                                             "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
 
 1535                                QStringLiteral( 
"http://osgeo.org/gdal" )  
 
 1539                                QObject::tr( 
"By default files are created with the line termination " 
 1540                                             "conventions of the local platform (CR/LF on win32 or LF " 
 1541                                             "on all other systems). This may be overridden through use " 
 1542                                             "of the LINEFORMAT layer creation option which may have a value " 
 1543                                             "of CRLF (DOS format) or LF (Unix format)." ),
 
 1545                                << QStringLiteral( 
"CRLF" )
 
 1546                                << QStringLiteral( 
"LF" ),
 
 1551       driverMetadata.insert( QStringLiteral( 
"GPX" ),
 
 1553                                QStringLiteral( 
"GPS eXchange Format [GPX]" ),
 
 1554                                QObject::tr( 
"GPS eXchange Format [GPX]" ),
 
 1555                                QStringLiteral( 
"*.gpx" ),
 
 1556                                QStringLiteral( 
"gpx" ),
 
 1559                                QStringLiteral( 
"UTF-8" )
 
 1564       datasetOptions.clear();
 
 1565       layerOptions.clear();
 
 1567       driverMetadata.insert( QStringLiteral( 
"Interlis 1" ),
 
 1569                                QStringLiteral( 
"INTERLIS 1" ),
 
 1570                                QObject::tr( 
"INTERLIS 1" ),
 
 1571                                QStringLiteral( 
"*.itf *.xml *.ili" ),
 
 1572                                QStringLiteral( 
"ili" ),
 
 1579       datasetOptions.clear();
 
 1580       layerOptions.clear();
 
 1582       driverMetadata.insert( QStringLiteral( 
"Interlis 2" ),
 
 1584                                QStringLiteral( 
"INTERLIS 2" ),
 
 1585                                QObject::tr( 
"INTERLIS 2" ),
 
 1586                                QStringLiteral( 
"*.xtf *.xml *.ili" ),
 
 1587                                QStringLiteral( 
"ili" ),
 
 1594       datasetOptions.clear();
 
 1595       layerOptions.clear();
 
 1598                                QObject::tr( 
"Allows you to specify the field to use for the KML <name> element." ),
 
 1599                                QStringLiteral( 
"Name" )  
 
 1603                                QObject::tr( 
"Allows you to specify the field to use for the KML <description> element." ),
 
 1604                                QStringLiteral( 
"Description" )  
 
 1608                                QObject::tr( 
"Allows you to specify the AltitudeMode to use for KML geometries. " 
 1609                                             "This will only affect 3D geometries and must be one of the valid KML options." ),
 
 1611                                << QStringLiteral( 
"clampToGround" )
 
 1612                                << QStringLiteral( 
"relativeToGround" )
 
 1613                                << QStringLiteral( 
"absolute" ),
 
 1614                                QStringLiteral( 
"relativeToGround" ) 
 
 1618                                QObject::tr( 
"The DOCUMENT_ID datasource creation option can be used to specified " 
 1619                                             "the id of the root <Document> node. The default value is root_doc." ),
 
 1620                                QStringLiteral( 
"root_doc" )  
 
 1623       driverMetadata.insert( QStringLiteral( 
"KML" ),
 
 1625                                QStringLiteral( 
"Keyhole Markup Language [KML]" ),
 
 1626                                QObject::tr( 
"Keyhole Markup Language [KML]" ),
 
 1627                                QStringLiteral( 
"*.kml" ),
 
 1628                                QStringLiteral( 
"kml" ),
 
 1631                                QStringLiteral( 
"UTF-8" )
 
 1636       datasetOptions.clear();
 
 1637       layerOptions.clear();
 
 1639       auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
 
 1642                                  QObject::tr( 
"Use this to turn on 'quick spatial index mode'. " 
 1643                                               "In this mode writing files can be about 5 times faster, " 
 1644                                               "but spatial queries can be up to 30 times slower." ),
 
 1646                                  << QStringLiteral( 
"QUICK" )
 
 1647                                  << QStringLiteral( 
"OPTIMIZED" ),
 
 1648                                  QStringLiteral( 
"QUICK" ), 
 
 1653                                  QObject::tr( 
"(multiples of 512): Block size for .map files. Defaults " 
 1654                                               "to 512. MapInfo 15.2 and above creates .tab files with a " 
 1655                                               "blocksize of 16384 bytes. Any MapInfo version should be " 
 1656                                               "able to handle block sizes from 512 to 32256." ),
 
 1660                                QObject::tr( 
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the " 
 1661                                             "accuracy of the coordinates. Note: the geometry of written " 
 1662                                             "features must be within the defined box." ),
 
 1666       insertMapInfoOptions( datasetOptions, layerOptions );
 
 1668       driverMetadata.insert( QStringLiteral( 
"MapInfo File" ),
 
 1670                                QStringLiteral( 
"Mapinfo" ),
 
 1671                                QObject::tr( 
"Mapinfo TAB" ),
 
 1672                                QStringLiteral( 
"*.tab" ),
 
 1673                                QStringLiteral( 
"tab" ),
 
 1678       datasetOptions.clear();
 
 1679       layerOptions.clear();
 
 1680       insertMapInfoOptions( datasetOptions, layerOptions );
 
 1683       driverMetadata.insert( QStringLiteral( 
"MapInfo MIF" ),
 
 1685                                QStringLiteral( 
"Mapinfo" ),
 
 1686                                QObject::tr( 
"Mapinfo MIF" ),
 
 1687                                QStringLiteral( 
"*.mif" ),
 
 1688                                QStringLiteral( 
"mif" ),
 
 1695       datasetOptions.clear();
 
 1696       layerOptions.clear();
 
 1699                                QObject::tr( 
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) " 
 1700                                             "seed file should be used. This option is ignored if the SEED option is provided." ),
 
 1705                                QObject::tr( 
"Override the seed file to use." ),
 
 1710                                QObject::tr( 
"Indicate whether the whole seed file should be copied. " 
 1711                                             "If not, only the first three elements will be copied." ),
 
 1716                                QObject::tr( 
"Indicates whether the color table should be copied from the seed file." ),
 
 1721                                QObject::tr( 
"Override the master unit name from the seed file with " 
 1722                                             "the provided one or two character unit name." ),
 
 1727                                QObject::tr( 
"Override the sub unit name from the seed file with the provided " 
 1728                                             "one or two character unit name." ),
 
 1733                                QObject::tr( 
"Override the number of subunits per master unit. " 
 1734                                             "By default the seed file value is used." ),
 
 1739                                QObject::tr( 
"Override the number of UORs (Units of Resolution) " 
 1740                                             "per sub unit. By default the seed file value is used." ),
 
 1745                                QObject::tr( 
"ORIGIN=x,y,z: Override the origin of the design plane. " 
 1746                                             "By default the origin from the seed file is used." ),
 
 1750       driverMetadata.insert( QStringLiteral( 
"DGN" ),
 
 1752                                QStringLiteral( 
"Microstation DGN" ),
 
 1753                                QObject::tr( 
"Microstation DGN" ),
 
 1754                                QStringLiteral( 
"*.dgn" ),
 
 1755                                QStringLiteral( 
"dgn" ),
 
 1762       datasetOptions.clear();
 
 1763       layerOptions.clear();
 
 1766                                QObject::tr( 
"Should update files be incorporated into the base data on the fly." ),
 
 1768                                << QStringLiteral( 
"APPLY" )
 
 1769                                << QStringLiteral( 
"IGNORE" ),
 
 1770                                QStringLiteral( 
"APPLY" ) 
 
 1774                                QObject::tr( 
"Should multipoint soundings be split into many single point sounding features. " 
 1775                                             "Multipoint geometries are not well handled by many formats, " 
 1776                                             "so it can be convenient to split single sounding features with many points " 
 1777                                             "into many single point features." ),
 
 1782                                QObject::tr( 
"Should a DEPTH attribute be added on SOUNDG features and assign the depth " 
 1783                                             "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is " 
 1789                                QObject::tr( 
"Should all the low level geometry primitives be returned as special " 
 1790                                             "IsolatedNode, ConnectedNode, Edge and Face layers." ),
 
 1795                                QObject::tr( 
"If enabled, numeric attributes assigned an empty string as a value will " 
 1796                                             "be preserved as a special numeric value. This option should not generally " 
 1797                                             "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
 
 1802                                QObject::tr( 
"Should LNAM and LNAM_REFS fields be attached to features capturing " 
 1803                                             "the feature to feature relationships in the FFPT group of the S-57 file." ),
 
 1808                                QObject::tr( 
"Should additional attributes relating features to their underlying " 
 1809                                             "geometric primitives be attached. These are the values of the FSPT group, " 
 1810                                             "and are primarily needed when doing S-57 to S-57 translations." ),
 
 1815                                QObject::tr( 
"Should attribute values be recoded to UTF-8 from the character encoding " 
 1816                                             "specified in the S57 DSSI record." ),
 
 1822       driverMetadata.insert( QStringLiteral( 
"S57" ),
 
 1824                                QStringLiteral( 
"S-57 Base file" ),
 
 1825                                QObject::tr( 
"S-57 Base file" ),
 
 1826                                QStringLiteral( 
"*.000" ),
 
 1827                                QStringLiteral( 
"000" ),
 
 1834       datasetOptions.clear();
 
 1835       layerOptions.clear();
 
 1837       driverMetadata.insert( QStringLiteral( 
"SDTS" ),
 
 1839                                QStringLiteral( 
"Spatial Data Transfer Standard [SDTS]" ),
 
 1840                                QObject::tr( 
"Spatial Data Transfer Standard [SDTS]" ),
 
 1841                                QStringLiteral( 
"*catd.ddf" ),
 
 1842                                QStringLiteral( 
"ddf" ),
 
 1849       datasetOptions.clear();
 
 1850       layerOptions.clear();
 
 1853                                QObject::tr( 
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 
 1854                                             "tables in a new database. By default these metadata tables are created " 
 1855                                             "when a new database is created." ),
 
 1861                                QStringLiteral( 
"NO" )
 
 1866                                QStringLiteral( 
"NO" )
 
 1870                              QObject::tr( 
"Controls the format used for the geometry column. Defaults to WKB. " 
 1871                                           "This is generally more space and processing efficient, but harder " 
 1872                                           "to inspect or use in simple applications than WKT (Well Known Text)." ),
 
 1874                              << QStringLiteral( 
"WKB" )
 
 1875                              << QStringLiteral( 
"WKT" ),
 
 1876                              QStringLiteral( 
"WKB" ) 
 
 1880                              QObject::tr( 
"Controls whether layer and field names will be laundered for easier use " 
 1881                                           "in SQLite. Laundered names will be converted to lower case and some special " 
 1882                                           "characters(' - #) will be changed to underscores." ),
 
 1887                              QStringLiteral( 
"NO" )
 
 1891                              QStringLiteral( 
"NO" )
 
 1899                              QObject::tr( 
"column_name1[,column_name2, …] A list of (String) columns that " 
 1900                                           "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 
 1901                                           "for databases that have big string blobs. However, use with care, since " 
 1902                                           "the value of such columns will be seen as compressed binary content with " 
 1903                                           "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 
 1904                                           "modifying or querying compressed columns, compression/decompression is " 
 1905                                           "done transparently. However, such columns cannot be (easily) queried with " 
 1906                                           "an attribute filter or WHERE clause. Note: in table definition, such columns " 
 1907                                           "have the 'VARCHAR_deflate' declaration type." ),
 
 1911       driverMetadata.insert( QStringLiteral( 
"SQLite" ),
 
 1913                                QStringLiteral( 
"SQLite" ),
 
 1914                                QObject::tr( 
"SQLite" ),
 
 1915                                QStringLiteral( 
"*.sqlite" ),
 
 1916                                QStringLiteral( 
"sqlite" ),
 
 1919                                QStringLiteral( 
"UTF-8" )
 
 1924       datasetOptions.clear();
 
 1925       layerOptions.clear();
 
 1928                                QObject::tr( 
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 
 1929                                             "tables in a new database. By default these metadata tables are created " 
 1930                                             "when a new database is created." ),
 
 1935                                QStringLiteral( 
"YES" )
 
 1939                                QObject::tr( 
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. " 
 1940                                             "Set to NO for regular SQLite databases." ),
 
 1945                              QStringLiteral( 
"SPATIALITE" )
 
 1949                              QObject::tr( 
"Controls whether layer and field names will be laundered for easier use " 
 1950                                           "in SQLite. Laundered names will be converted to lower case and some special " 
 1951                                           "characters(' - #) will be changed to underscores." ),
 
 1956                              QObject::tr( 
"If the database is of the SpatiaLite flavor, and if OGR is linked " 
 1957                                           "against libspatialite, this option can be used to control if a spatial " 
 1958                                           "index must be created." ),
 
 1963                              QObject::tr( 
"If the format of the geometry BLOB is of the SpatiaLite flavor, " 
 1964                                           "this option can be used to control if the compressed format for " 
 1965                                           "geometries (LINESTRINGs, POLYGONs) must be used." ),
 
 1970                              QObject::tr( 
"Used to force the SRID number of the SRS associated with the layer. " 
 1971                                           "When this option isn't specified and that a SRS is associated with the " 
 1972                                           "layer, a search is made in the spatial_ref_sys to find a match for the " 
 1973                                           "SRS, and, if there is no match, a new entry is inserted for the SRS in " 
 1974                                           "the spatial_ref_sys table. When the SRID option is specified, this " 
 1975                                           "search (and the eventual insertion of a new entry) will not be done: " 
 1976                                           "the specified SRID is used as such." ),
 
 1981                              QObject::tr( 
"column_name1[,column_name2, …] A list of (String) columns that " 
 1982                                           "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 
 1983                                           "for databases that have big string blobs. However, use with care, since " 
 1984                                           "the value of such columns will be seen as compressed binary content with " 
 1985                                           "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 
 1986                                           "modifying or queryings compressed columns, compression/decompression is " 
 1987                                           "done transparently. However, such columns cannot be (easily) queried with " 
 1988                                           "an attribute filter or WHERE clause. Note: in table definition, such columns " 
 1989                                           "have the 'VARCHAR_deflate' declaration type." ),
 
 1993       driverMetadata.insert( QStringLiteral( 
"SpatiaLite" ),
 
 1995                                QStringLiteral( 
"SpatiaLite" ),
 
 1996                                QObject::tr( 
"SpatiaLite" ),
 
 1997                                QStringLiteral( 
"*.sqlite" ),
 
 1998                                QStringLiteral( 
"sqlite" ),
 
 2001                                QStringLiteral( 
"UTF-8" )
 
 2005       datasetOptions.clear();
 
 2006       layerOptions.clear();
 
 2009                                QObject::tr( 
"Override the header file used - in place of header.dxf." ),
 
 2014                                QObject::tr( 
"Override the trailer file used - in place of trailer.dxf." ),
 
 2018       driverMetadata.insert( QStringLiteral( 
"DXF" ),
 
 2020                                QStringLiteral( 
"AutoCAD DXF" ),
 
 2021                                QObject::tr( 
"AutoCAD DXF" ),
 
 2022                                QStringLiteral( 
"*.dxf" ),
 
 2023                                QStringLiteral( 
"dxf" ),
 
 2030       datasetOptions.clear();
 
 2031       layerOptions.clear();
 
 2034                                QObject::tr( 
"Indicates the GeoConcept export file extension. " 
 2035                                             "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
 
 2037                                << QStringLiteral( 
"GXT" )
 
 2038                                << QStringLiteral( 
"TXT" ),
 
 2039                                QStringLiteral( 
"GXT" ) 
 
 2043                                QObject::tr( 
"Path to the GCT: the GCT file describes the GeoConcept types definitions: " 
 2044                                             "In this file, every line must start with //# followed by a keyword. " 
 2045                                             "Lines starting with // are comments." ),
 
 2050                                QObject::tr( 
"Defines the feature to be created. The TYPE corresponds to one of the Name " 
 2051                                             "found in the GCT file for a type section. The SUBTYPE corresponds to one of " 
 2052                                             "the Name found in the GCT file for a sub-type section within the previous " 
 2057       driverMetadata.insert( QStringLiteral( 
"Geoconcept" ),
 
 2059                                QStringLiteral( 
"Geoconcept" ),
 
 2060                                QObject::tr( 
"Geoconcept" ),
 
 2061                                QStringLiteral( 
"*.gxt *.txt" ),
 
 2062                                QStringLiteral( 
"gxt" ),
 
 2069       datasetOptions.clear();
 
 2070       layerOptions.clear();
 
 2073                              QObject::tr( 
"When this option is set, the new layer will be created inside the named " 
 2074                                           "FeatureDataset folder. If the folder does not already exist, it will be created." ),
 
 2079                              QObject::tr( 
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
 
 2080                              QStringLiteral( 
"SHAPE" )  
 
 2084                              QObject::tr( 
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
 
 2085                              QStringLiteral( 
"OBJECTID" )  
 
 2088       driverMetadata.insert( QStringLiteral( 
"FileGDB" ),
 
 2090                                QStringLiteral( 
"ESRI FileGDB" ),
 
 2091                                QObject::tr( 
"ESRI FileGDB" ),
 
 2092                                QStringLiteral( 
"*.gdb" ),
 
 2093                                QStringLiteral( 
"gdb" ),
 
 2096                                QStringLiteral( 
"UTF-8" )
 
 2101       datasetOptions.clear();
 
 2102       layerOptions.clear();
 
 2105                              QObject::tr( 
"By default, the driver will try to detect the data type of fields. If set " 
 2106                                           "to STRING, all fields will be of String type." ),
 
 2108                              << QStringLiteral( 
"AUTO" )
 
 2109                              << QStringLiteral( 
"STRING" ),
 
 2110                              QStringLiteral( 
"AUTO" ), 
 
 2115                              QObject::tr( 
"By default, the driver will read the first lines of each sheet to detect " 
 2116                                           "if the first line might be the name of columns. If set to FORCE, the driver " 
 2117                                           "will consider the first line as the header line. If set to " 
 2118                                           "DISABLE, it will be considered as the first feature. Otherwise " 
 2119                                           "auto-detection will occur." ),
 
 2121                              << QStringLiteral( 
"FORCE" )
 
 2122                              << QStringLiteral( 
"DISABLE" )
 
 2123                              << QStringLiteral( 
"AUTO" ),
 
 2124                              QStringLiteral( 
"AUTO" ), 
 
 2128       driverMetadata.insert( QStringLiteral( 
"XLSX" ),
 
 2130                                QStringLiteral( 
"MS Office Open XML spreadsheet" ),
 
 2131                                QObject::tr( 
"MS Office Open XML spreadsheet [XLSX]" ),
 
 2132                                QStringLiteral( 
"*.xlsx" ),
 
 2133                                QStringLiteral( 
"xlsx" ),
 
 2136                                QStringLiteral( 
"UTF-8" )
 
 2141       datasetOptions.clear();
 
 2142       layerOptions.clear();
 
 2145                              QObject::tr( 
"By default, the driver will try to detect the data type of fields. If set " 
 2146                                           "to STRING, all fields will be of String type." ),
 
 2148                              << QStringLiteral( 
"AUTO" )
 
 2149                              << QStringLiteral( 
"STRING" ),
 
 2150                              QStringLiteral( 
"AUTO" ), 
 
 2155                              QObject::tr( 
"By default, the driver will read the first lines of each sheet to detect " 
 2156                                           "if the first line might be the name of columns. If set to FORCE, the driver " 
 2157                                           "will consider the first line as the header line. If set to " 
 2158                                           "DISABLE, it will be considered as the first feature. Otherwise " 
 2159                                           "auto-detection will occur." ),
 
 2161                              << QStringLiteral( 
"FORCE" )
 
 2162                              << QStringLiteral( 
"DISABLE" )
 
 2163                              << QStringLiteral( 
"AUTO" ),
 
 2164                              QStringLiteral( 
"AUTO" ), 
 
 2168       driverMetadata.insert( QStringLiteral( 
"ODS" ),
 
 2170                                QStringLiteral( 
"Open Document Spreadsheet" ),
 
 2171                                QObject::tr( 
"Open Document Spreadsheet [ODS]" ),
 
 2172                                QStringLiteral( 
"*.ods" ),
 
 2173                                QStringLiteral( 
"ods" ),
 
 2176                                QStringLiteral( 
"UTF-8" )
 
 2181       datasetOptions.clear();
 
 2182       layerOptions.clear();
 
 2185                                QObject::tr( 
"Line termination character sequence." ),
 
 2187                                << QStringLiteral( 
"CRLF" )
 
 2188                                << QStringLiteral( 
"LF" ),
 
 2189                                QStringLiteral( 
"LF" ), 
 
 2195                              QObject::tr( 
"Format of geometry columns." ),
 
 2197                              << QStringLiteral( 
"geometry" )
 
 2198                              << QStringLiteral( 
"geography" ),
 
 2199                              QStringLiteral( 
"geometry" ), 
 
 2204                              QObject::tr( 
"Controls whether layer and field names will be laundered for easier use. " 
 2205                                           "Laundered names will be converted to lower case and some special " 
 2206                                           "characters(' - #) will be changed to underscores." ),
 
 2211                              QObject::tr( 
"Name for the geometry column. Defaults to wkb_geometry " 
 2212                                           "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
 
 2215                              QObject::tr( 
"Name of schema into which to create the new table" ) ) );
 
 2218                              QObject::tr( 
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
 
 2223                              QObject::tr( 
"Whether to explicitly recreate the table if necessary." ),
 
 2228                              QObject::tr( 
"Whether to explicitly destroy tables before recreating them." ),
 
 2230                              << QStringLiteral( 
"YES" )
 
 2231                              << QStringLiteral( 
"NO" )
 
 2232                              << QStringLiteral( 
"IF_EXISTS" ),
 
 2233                              QStringLiteral( 
"YES" ), 
 
 2238                              QObject::tr( 
"Used to force the SRID number of the SRS associated with the layer. " 
 2239                                           "When this option isn't specified and that a SRS is associated with the " 
 2240                                           "layer, a search is made in the spatial_ref_sys to find a match for the " 
 2241                                           "SRS, and, if there is no match, a new entry is inserted for the SRS in " 
 2242                                           "the spatial_ref_sys table. When the SRID option is specified, this " 
 2243                                           "search (and the eventual insertion of a new entry) will not be done: " 
 2244                                           "the specified SRID is used as such." ),
 
 2249                              QObject::tr( 
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. " 
 2250                                           "Important to set it correctly if using non-linear geometry types" ),
 
 2251                              QStringLiteral( 
"2.2" ) 
 
 2254       driverMetadata.insert( QStringLiteral( 
"PGDUMP" ),
 
 2256                                QStringLiteral( 
"PostgreSQL SQL dump" ),
 
 2257                                QObject::tr( 
"PostgreSQL SQL dump" ),
 
 2258                                QStringLiteral( 
"*.sql" ),
 
 2259                                QStringLiteral( 
"sql" ),
 
 2262                                QStringLiteral( 
"UTF-8" )
 
 2268     QgsVectorFileWriterMetadataContainer( 
const QgsVectorFileWriterMetadataContainer &other ) = 
delete;
 
 2269     QgsVectorFileWriterMetadataContainer &operator=( 
const QgsVectorFileWriterMetadataContainer &other ) = 
delete;
 
 2270     ~QgsVectorFileWriterMetadataContainer()
 
 2272       for ( 
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
 
 2274         for ( 
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
 
 2275           delete optionIt.value();
 
 2276         for ( 
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
 
 2277           delete optionIt.value();
 
 2281     QMap<QString,  QgsVectorFileWriter::MetaData> driverMetadata;
 
 2288   static QgsVectorFileWriterMetadataContainer sDriverMetadata;
 
 2289   QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
 
 2291   for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
 
 2293     if ( it.key() == QLatin1String( 
"PGDUMP" ) &&
 
 2294          driverName != QLatin1String( 
"PGDUMP" ) &&
 
 2295          driverName != QLatin1String( 
"PostgreSQL SQL dump" ) )
 
 2300     if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
 
 2315     return QStringList();
 
 2324     return QStringList();
 
 2331   OGRwkbGeometryType ogrType = 
static_cast<OGRwkbGeometryType
>( type );
 
 2357   QgsFeatureList::iterator fIt = features.begin();
 
 2359   for ( ; fIt != features.end(); ++fIt )
 
 2384     QString styleString;
 
 2385     QString currentStyle;
 
 2387     QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
 
 2388     for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
 
 2390       int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
 
 2391       for ( 
int i = 0; i < nSymbolLayers; ++i )
 
 2394         QMap< QgsSymbolLayer *, QString >::const_iterator it = 
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
 
 2400         double mmsf = mmScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
 
 2401         double musf = mapUnitScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
 
 2403         currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
 
 2407           if ( symbolIt != symbols.constBegin() || i != 0 )
 
 2409             styleString.append( 
';' );
 
 2411           styleString.append( currentStyle );
 
 2415           OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
 
 2416           if ( !writeFeature( 
mLayer, poFeature.get() ) )
 
 2423     OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
 
 2428     if ( !writeFeature( 
mLayer, poFeature.get() ) )
 
 2447     int fldIdx = it.key();
 
 2448     int ogrField = it.value();
 
 2450     QVariant attrValue = feature.
attribute( fldIdx );
 
 2453     if ( !attrValue.isValid() || attrValue.isNull() )
 
 2462 #ifdef OGRNullMarker 
 2463       OGR_F_SetFieldNull( poFeature.get(), ogrField );
 
 2478       mErrorMessage = QObject::tr( 
"Error converting value (%1) for attribute field %2: %3" )
 
 2479                       .arg( feature.
attribute( fldIdx ).toString(),
 
 2489         OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
 
 2491       case QVariant::LongLong:
 
 2492         OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
 
 2494       case QVariant::Bool:
 
 2495         OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
 
 2497       case QVariant::String:
 
 2498         OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toString() ).constData() );
 
 2500       case QVariant::Double:
 
 2501         OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
 
 2503       case QVariant::Date:
 
 2504         OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
 
 2505                                 attrValue.toDate().year(),
 
 2506                                 attrValue.toDate().month(),
 
 2507                                 attrValue.toDate().day(),
 
 2510       case QVariant::DateTime:
 
 2513           OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral( 
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
 
 2517           OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
 
 2518                                   attrValue.toDateTime().date().year(),
 
 2519                                   attrValue.toDateTime().date().month(),
 
 2520                                   attrValue.toDateTime().date().day(),
 
 2521                                   attrValue.toDateTime().time().hour(),
 
 2522                                   attrValue.toDateTime().time().minute(),
 
 2523                                   attrValue.toDateTime().time().second(),
 
 2527       case QVariant::Time:
 
 2530           OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toString() ).constData() );
 
 2534           OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
 
 2536                                   attrValue.toTime().hour(),
 
 2537                                   attrValue.toTime().minute(),
 
 2538                                   attrValue.toTime().second(),
 
 2543       case QVariant::ByteArray:
 
 2545         const QByteArray ba = attrValue.toByteArray();
 
 2546         OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(), 
const_cast< GByte * 
>( 
reinterpret_cast< const GByte * 
>( ba.data() ) ) );
 
 2550       case QVariant::Invalid:
 
 2553       case QVariant::StringList:
 
 2558           const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
 
 2560           if ( !doc.isNull() )
 
 2562             jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
 
 2564           OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( jsonString.constData() ) );
 
 2568         QStringList list = attrValue.toStringList();
 
 2569         if ( mSupportedListSubTypes.contains( QVariant::String ) )
 
 2571           int count = list.count();
 
 2572           char **lst = 
new char *[count + 1];
 
 2576             for ( 
const QString &
string : list )
 
 2578               lst[pos] = CPLStrdup( 
mCodec->fromUnicode( 
string ).data() );
 
 2582           lst[count] = 
nullptr;
 
 2583           OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
 
 2588           OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( list.join( 
',' ) ).constData() );
 
 2593       case QVariant::List:
 
 2597           const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
 
 2599           if ( !doc.isNull() )
 
 2601             jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
 
 2603           OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( jsonString.constData() ) );
 
 2610           QStringList list = attrValue.toStringList();
 
 2611           if ( mSupportedListSubTypes.contains( QVariant::String ) )
 
 2613             int count = list.count();
 
 2614             char **lst = 
new char *[count + 1];
 
 2618               for ( 
const QString &
string : list )
 
 2620                 lst[pos] = CPLStrdup( 
mCodec->fromUnicode( 
string ).data() );
 
 2624             lst[count] = 
nullptr;
 
 2625             OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
 
 2630             OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( list.join( 
',' ) ).constData() );
 
 2636           const QVariantList list = attrValue.toList();
 
 2637           if ( mSupportedListSubTypes.contains( QVariant::Int ) )
 
 2639             const int count = list.count();
 
 2640             int *lst = 
new int[count];
 
 2644               for ( 
const QVariant &value : list )
 
 2646                 lst[pos] = value.toInt();
 
 2650             OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
 
 2655             QStringList strings;
 
 2656             strings.reserve( list.size() );
 
 2657             for ( 
const QVariant &value : list )
 
 2659               strings << QString::number( value.toInt() );
 
 2661             OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 2667           const QVariantList list = attrValue.toList();
 
 2668           if ( mSupportedListSubTypes.contains( QVariant::Double ) )
 
 2670             const int count = list.count();
 
 2671             double *lst = 
new double[count];
 
 2675               for ( 
const QVariant &value : list )
 
 2677                 lst[pos] = value.toDouble();
 
 2681             OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
 
 2686             QStringList strings;
 
 2687             strings.reserve( list.size() );
 
 2688             for ( 
const QVariant &value : list )
 
 2690               strings << QString::number( value.toDouble() );
 
 2692             OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 2698           const QVariantList list = attrValue.toList();
 
 2699           if ( mSupportedListSubTypes.contains( QVariant::LongLong ) )
 
 2701             const int count = list.count();
 
 2702             long long *lst = 
new long long[count];
 
 2706               for ( 
const QVariant &value : list )
 
 2708                 lst[pos] = value.toLongLong();
 
 2712             OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
 
 2717             QStringList strings;
 
 2718             strings.reserve( list.size() );
 
 2719             for ( 
const QVariant &value : list )
 
 2721               strings << QString::number( value.toLongLong() );
 
 2723             OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 2731         mErrorMessage = QObject::tr( 
"Invalid variant type for field %1[%2]: received %3 with type %4" )
 
 2734                         .arg( attrValue.typeName(),
 
 2735                               attrValue.toString() );
 
 2748       if ( mCoordinateTransform )
 
 2753           geom.
transform( *mCoordinateTransform );
 
 2771         OGRGeometryH mGeom2 = 
nullptr;
 
 2817           mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 2818                           .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 2824         QByteArray wkb( geom.
asWkb() );
 
 2825         OGRErr err = OGR_G_ImportFromWkb( mGeom2, 
reinterpret_cast<unsigned char *
>( 
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
 
 2826         if ( err != OGRERR_NONE )
 
 2828           mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 2829                           .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 2836         OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
 
 2842         OGRErr err = OGR_G_ImportFromWkb( ogrGeom, 
reinterpret_cast<unsigned char *
>( 
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
 
 2843         if ( err != OGRERR_NONE )
 
 2845           mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 2846                           .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 2853         OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
 
 2868   for ( 
int i = 0; i < attributes.size(); i++ )
 
 2870     if ( omap.find( i ) != omap.end() )
 
 2875 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
 
 2877   if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
 
 2879     mErrorMessage = QObject::tr( 
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 2889   if ( mUsingTransaction )
 
 2891     if ( OGRERR_NONE != OGR_L_CommitTransaction( 
mLayer ) )
 
 2893       QgsDebugMsg( QStringLiteral( 
"Error while committing transaction on OGRLayer." ) );
 
 2897 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) && GDAL_VERSION_NUM <= GDAL_COMPUTE_VERSION(3,1,3) 
 2901     QString drvName = GDALGetDriverShortName( GDALGetDatasetDriver( 
mDS.get() ) );
 
 2902     if ( drvName == QLatin1String( 
"XLSX" ) ||
 
 2903          drvName == QLatin1String( 
"ODS" ) )
 
 2905       CPLSetThreadLocalConfigOption( 
"CPL_CREATE_ZIP64", 
"NO" );
 
 2907       CPLSetThreadLocalConfigOption( 
"CPL_CREATE_ZIP64", 
nullptr );
 
 2915     mFilename = QString::fromUtf8( GDALGetDescription( 
mDS.get() ) );
 
 2920   if ( !mFilename.isEmpty() )
 
 2922     QgsOgrProviderUtils::invalidateCachedDatasets( mFilename );
 
 2933     const QString &fileName,
 
 2934     const QString &fileEncoding,
 
 2936     const QString &driverName,
 
 2938     QString *errorMessage,
 
 2939     const QStringList &datasourceOptions,
 
 2940     const QStringList &layerOptions,
 
 2941     bool skipAttributeCreation,
 
 2942     QString *newFilename,
 
 2944     double symbologyScale,
 
 2954   if ( destCRS.
isValid() && layer )
 
 2980     const QString &fileName,
 
 2981     const QString &fileEncoding,
 
 2983     const QString &driverName,
 
 2985     QString *errorMessage,
 
 2986     const QStringList &datasourceOptions,
 
 2987     const QStringList &layerOptions,
 
 2988     bool skipAttributeCreation,
 
 2989     QString *newFilename,
 
 2991     double symbologyScale,
 
 3022   : driverName( QStringLiteral( 
"GPKG" ) )
 
 3030   if ( !layer || !layer->
isValid() )
 
 3037   details.sourceCrs = layer->
crs();
 
 3038   details.sourceWkbType = layer->
wkbType();
 
 3039   details.sourceFields = layer->
fields();
 
 3048   if ( details.storageType == QLatin1String( 
"ESRI Shapefile" ) )
 
 3056     details.geometryTypeScanIterator = layer->
getFeatures( req );
 
 3060   details.renderContext.setExpressionContext( details.expressionContext );
 
 3061   details.renderContext.setRendererScale( options.
symbologyScale );
 
 3063   details.shallTransform = 
false;
 
 3068     details.shallTransform = 
true;
 
 3073     details.outputCrs = details.sourceCrs;
 
 3076   details.destWkbType = details.sourceWkbType;
 
 3090     details.attributes.clear();
 
 3091   else if ( details.attributes.isEmpty() )
 
 3093     const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
 
 3094     for ( 
int idx : allAttributes )
 
 3096       QgsField fld = details.sourceFields.at( idx );
 
 3097       if ( details.providerType == QLatin1String( 
"oracle" ) && fld.
typeName().contains( QLatin1String( 
"SDO_GEOMETRY" ) ) )
 
 3099       details.attributes.append( idx );
 
 3103   if ( !details.attributes.isEmpty() )
 
 3105     for ( 
int attrIdx : std::as_const( details.attributes ) )
 
 3107       details.outputFields.append( details.sourceFields.at( attrIdx ) );
 
 3113   if ( details.providerType == QLatin1String( 
"spatialite" ) )
 
 3115     for ( 
int i = 0; i < details.outputFields.size(); i++ )
 
 3117       if ( details.outputFields.at( i ).type() == QVariant::LongLong )
 
 3122         if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
 
 3124           details.outputFields[i].setType( QVariant::Int );
 
 3132   addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
 
 3142     bool useFilterRect = 
true;
 
 3143     if ( details.shallTransform )
 
 3150         filterRect = extentTransform.
transformBoundingBox( filterRect, Qgis::TransformDirection::Reverse );
 
 3154         useFilterRect = 
false;
 
 3157     if ( useFilterRect )
 
 3163     details.filterRectEngine->prepareGeometry();
 
 3165   details.sourceFeatureIterator = layer->
getFeatures( req );
 
 3179   int lastProgressReport = 0;
 
 3180   long long total = details.featureCount;
 
 3183   if ( details.providerType == QLatin1String( 
"ogr" ) && !details.dataSourceUri.isEmpty() )
 
 3185     QString srcFileName( details.providerUriParams.value( QStringLiteral( 
"path" ) ).toString() );
 
 3186     if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
 
 3190       if ( !( ( options.
driverName == QLatin1String( 
"GPKG" ) ||
 
 3191                 options.
driverName == QLatin1String( 
"SpatiaLite" ) ||
 
 3192                 options.
driverName == QLatin1String( 
"SQLite" ) ) &&
 
 3193               options.
layerName != details.providerUriParams.value( QStringLiteral( 
"layerName" ) ) ) )
 
 3196           *
errorMessage = QObject::tr( 
"Cannot overwrite a OGR layer in place" );
 
 3216           int newProgress = 
static_cast<int>( ( 5.0 * scanned ) / total );
 
 3217           if ( newProgress != lastProgressReport )
 
 3219             lastProgressReport = newProgress;
 
 3234   QString tempNewFilename;
 
 3235   QString tempNewLayer;
 
 3237   std::unique_ptr< QgsVectorFileWriter > writer( 
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
 
 3241     *newFilename = tempNewFilename;
 
 3244     *newLayer = tempNewLayer;
 
 3284   int n = 0, errors = 0;
 
 3293   writer->startRender( details.renderer.get(), details.sourceFields );
 
 3295   writer->resetMap( details.attributes );
 
 3297   writer->mFields = details.sourceFields;
 
 3301   int initialProgress = lastProgressReport;
 
 3302   while ( details.sourceFeatureIterator.nextFeature( fet ) )
 
 3313       int newProgress = 
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
 
 3314       if ( newProgress < 100 && newProgress != lastProgressReport )
 
 3316         lastProgressReport = newProgress;
 
 3321     if ( details.shallTransform )
 
 3334         QString msg = QObject::tr( 
"Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
 
 3335                       .arg( fet.
id() ).arg( e.
what() );
 
 3352     if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
 
 3359           *
errorMessage = QObject::tr( 
"Feature write errors:" );
 
 3365       if ( errors > 1000 )
 
 3369           *
errorMessage += QObject::tr( 
"Stopping after %n error(s)", 
nullptr, errors );
 
 3379   writer->stopRender();
 
 3383     *
errorMessage += QObject::tr( 
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
 
 3388   bool metadataFailure = 
false;
 
 3393       {QStringLiteral( 
"path" ), tempNewFilename },
 
 3394       {QStringLiteral( 
"layerName" ), tempNewLayer }
 
 3408         metadataFailure = 
true;
 
 3419       metadataFailure = 
true;
 
 3427     const QString &fileName,
 
 3429     QString *newFilename,
 
 3433   QgsVectorFileWriter::PreparedWriterDetails details;
 
 3434   WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 3442     const QString &fileName,
 
 3445     QString *newFilename,
 
 3449   QgsVectorFileWriter::PreparedWriterDetails details;
 
 3450   WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 3459   QgsVectorFileWriter::PreparedWriterDetails details;
 
 3460   WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 3469   QFileInfo fi( fileName );
 
 3470   QDir dir = fi.dir();
 
 3473   for ( 
const char *suffix : { 
".shp", 
".shx", 
".dbf", 
".prj", 
".qix", 
".qpj", 
".cpg", 
".sbn", 
".sbx", 
".idm", 
".ind" } )
 
 3475     filter << fi.completeBaseName() + suffix;
 
 3479   const auto constEntryList = dir.entryList( filter );
 
 3480   for ( 
const QString &file : constEntryList )
 
 3482     QFile f( dir.canonicalPath() + 
'/' + file );
 
 3485       QgsDebugMsg( QStringLiteral( 
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
 
 3501   static QReadWriteLock sFilterLock;
 
 3502   static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
 
 3506   const auto it = sFilters.constFind( options );
 
 3507   if ( it != sFilters.constEnd() )
 
 3511   QList< QgsVectorFileWriter::FilterFormatDetails > results;
 
 3514   int const drvCount = OGRGetDriverCount();
 
 3516   for ( 
int i = 0; i < drvCount; ++i )
 
 3518     OGRSFDriverH drv = OGRGetDriver( i );
 
 3521       QString drvName = OGR_Dr_GetName( drv );
 
 3523       GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
 
 3524       char **metadata = 
nullptr;
 
 3527         metadata = GDALGetMetadata( gdalDriver, 
nullptr );
 
 3530       bool nonSpatialFormat = CSLFetchBoolean( metadata, GDAL_DCAP_NONSPATIAL, 
false );
 
 3532       if ( OGR_Dr_TestCapability( drv, 
"CreateDataSource" ) != 0 )
 
 3537           if ( nonSpatialFormat )
 
 3542         if ( filterString.isEmpty() )
 
 3549           globs = metadata.
glob.toLower().split( 
' ' );
 
 3555         details.
globs = globs;
 
 3564     if ( options & SortRecommended )
 
 3566       if ( a.driverName == QLatin1String( 
"GPKG" ) )
 
 3568       else if ( b.driverName == QLatin1String( 
"GPKG" ) )
 
 3570       else if ( a.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3572       else if ( b.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3579   sFilters.insert( options, results );
 
 3586   QSet< QString > extensions;
 
 3588   const QRegularExpression rx( QStringLiteral( 
"\\*\\.(.*)$" ) );
 
 3592     for ( 
const QString &glob : format.globs )
 
 3594       const QRegularExpressionMatch match = rx.match( glob );
 
 3595       if ( !match.hasMatch() )
 
 3598       const QString matched = match.captured( 1 );
 
 3599       extensions.insert( matched );
 
 3603   QStringList extensionList = qgis::setToList( extensions );
 
 3605   std::sort( extensionList.begin(), extensionList.end(), [options]( 
const QString & a, 
const QString & b ) -> 
bool 
 3607     if ( options & SortRecommended )
 
 3609       if ( a == QLatin1String( 
"gpkg" ) )
 
 3611       else if ( b == QLatin1String( 
"gpkg" ) )
 
 3613       else if ( a == QLatin1String( 
"shp" ) )
 
 3615       else if ( b == QLatin1String( 
"shp" ) )
 
 3619     return a.toLower().localeAwareCompare( b.toLower() ) < 0;
 
 3622   return extensionList;
 
 3627   QList< QgsVectorFileWriter::DriverDetails > results;
 
 3630   const int drvCount = OGRGetDriverCount();
 
 3632   QStringList writableDrivers;
 
 3633   for ( 
int i = 0; i < drvCount; ++i )
 
 3635     OGRSFDriverH drv = OGRGetDriver( i );
 
 3638       QString drvName = OGR_Dr_GetName( drv );
 
 3644         if ( drvName == QLatin1String( 
"ODS" ) || drvName == QLatin1String( 
"XLSX" ) || drvName == QLatin1String( 
"XLS" ) )
 
 3648       if ( drvName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3650         writableDrivers << QStringLiteral( 
"DBF file" );
 
 3652       if ( OGR_Dr_TestCapability( drv, 
"CreateDataSource" ) != 0 )
 
 3655         if ( drvName == QLatin1String( 
"MapInfo File" ) )
 
 3657           writableDrivers << QStringLiteral( 
"MapInfo MIF" );
 
 3659         else if ( drvName == QLatin1String( 
"SQLite" ) )
 
 3666           QString option = QStringLiteral( 
"SPATIALITE=YES" );
 
 3667           char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ), 
nullptr };
 
 3668           OGRSFDriverH poDriver;
 
 3670           poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
 
 3673             gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral( 
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
 
 3676               writableDrivers << QStringLiteral( 
"SpatiaLite" );
 
 3677               OGR_Dr_DeleteDataSource( poDriver, QStringLiteral( 
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
 
 3680           CPLFree( options[0] );
 
 3682         writableDrivers << drvName;
 
 3687   results.reserve( writableDrivers.count() );
 
 3688   for ( 
const QString &drvName : std::as_const( writableDrivers ) )
 
 3702     if ( options & SortRecommended )
 
 3704       if ( a.driverName == QLatin1String( 
"GPKG" ) )
 
 3706       else if ( b.driverName == QLatin1String( 
"GPKG" ) )
 
 3708       else if ( a.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3710       else if ( b.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3714     return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
 
 3721   QString ext = extension.trimmed();
 
 3722   if ( ext.isEmpty() )
 
 3725   if ( ext.startsWith( 
'.' ) )
 
 3729   int const drvCount = GDALGetDriverCount();
 
 3731   for ( 
int i = 0; i < drvCount; ++i )
 
 3733     GDALDriverH drv = GDALGetDriver( i );
 
 3739         QString drvName = GDALGetDriverShortName( drv );
 
 3740         QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, 
nullptr ) ).split( 
' ' );
 
 3742         const auto constDriverExtensions = driverExtensions;
 
 3743         for ( 
const QString &driver : constDriverExtensions )
 
 3745           if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
 
 3756   QString filterString;
 
 3760     if ( !filterString.isEmpty() )
 
 3761       filterString += QLatin1String( 
";;" );
 
 3763     filterString += details.filterString;
 
 3765   return filterString;
 
 3774   return QStringLiteral( 
"%1 (%2 %3)" ).arg( metadata.
trLongName,
 
 3775          metadata.
glob.toLower(),
 
 3776          metadata.
glob.toUpper() );
 
 3781   if ( codecName == QLatin1String( 
"System" ) )
 
 3782     return QStringLiteral( 
"LDID/0" );
 
 3784   const QRegularExpression re( QRegularExpression::anchoredPattern( QString( 
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 3785   const QRegularExpressionMatch match = re.match( codecName );
 
 3786   if ( match.hasMatch() )
 
 3788     QString 
c = match.captured( 2 ).remove( 
'-' );
 
 3790     ( void ) 
c.toInt( &isNumber );
 
 3818   OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
 
 3819   OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
 
 3822   int nTotalLevels = 0;
 
 3824   QgsSymbolList::iterator symbolIt = symbolList.begin();
 
 3825   for ( ; symbolIt != symbolList.end(); ++symbolIt )
 
 3827     double mmsf = mmScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
 
 3828     double musf = mapUnitScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
 
 3830     int nLevels = ( *symbolIt )->symbolLayerCount();
 
 3831     for ( 
int i = 0; i < nLevels; ++i )
 
 3833       mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
 
 3834       OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
 
 3835                        ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
 
 3839   OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
 
 3845   if ( !details.renderer )
 
 3850   QHash< QgsSymbol *, QList<QgsFeature> > features;
 
 3859   startRender( details.renderer.get(), details.sourceFields );
 
 3879         QString msg = QObject::tr( 
"Failed to transform, writing stopped. (Exception: %1)" )
 
 3890     featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
 
 3891     if ( !featureSymbol )
 
 3896     QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
 
 3897     if ( it == features.end() )
 
 3899       it = features.insert( featureSymbol, QList<QgsFeature>() );
 
 3901     it.value().append( fet );
 
 3906   QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
 
 3907   for ( 
int i = 0; i < symbols.count(); i++ )
 
 3913       if ( level < 0 || level >= 1000 ) 
 
 3916       while ( level >= levels.count() ) 
 
 3918       levels[level].append( item );
 
 3923   int nTotalFeatures = 0;
 
 3926   for ( 
int l = 0; l < levels.count(); l++ )
 
 3929     for ( 
int i = 0; i < level.count(); i++ )
 
 3932       QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
 
 3933       if ( levelIt == features.end() )
 
 3939       double mmsf = mmScaleFactor( 
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
 
 3940       double musf = mapUnitScaleFactor( 
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
 
 3942       int llayer = item.
layer();
 
 3943       QList<QgsFeature> &featureList = levelIt.value();
 
 3944       QList<QgsFeature>::iterator featureIt = featureList.begin();
 
 3945       for ( ; featureIt != featureList.end(); ++featureIt )
 
 3955         QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
 
 3956         if ( !styleString.isEmpty() )
 
 3958           OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
 
 3959           if ( !writeFeature( 
mLayer, ogrFeature.get() ) )
 
 3972     *
errorMessage += QObject::tr( 
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
 
 3989       return 1000 / scale;
 
 4006       return scale / 1000;
 
 4014   mRenderer = createSymbologyRenderer( sourceRenderer );
 
 4020   mRenderer->startRender( mRenderContext,  fields );
 
 4023 void QgsVectorFileWriter::stopRender()
 
 4030   mRenderer->stopRender( mRenderContext );
 
 4033 std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer( 
QgsFeatureRenderer *sourceRenderer )
 const 
 4039   if ( !sourceRenderer )
 
 4044   return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
 
 4051     const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
 
 4052     for ( 
const QString &attr : rendererAttributes )
 
 4057         attList.append( index );
 
 4063 QStringList QgsVectorFileWriter::concatenateOptions( 
const QMap<QString, QgsVectorFileWriter::Option *> &options )
 
 4066   QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
 
 4068   for ( it = options.constBegin(); it != options.constEnd(); ++it )
 
 4071     switch ( option->
type )
 
 4078           list.append( QStringLiteral( 
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
 
 4088           list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
 
 4098           list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
 
 4107           list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
mValue ) );
 
 4118   OGRSFDriverH hDriver = 
nullptr;
 
 4121     return QgsVectorFileWriter::EditionCapabilities();
 
 4122   QString drvName = OGR_Dr_GetName( hDriver );
 
 4123   QgsVectorFileWriter::EditionCapabilities caps = QgsVectorFileWriter::EditionCapabilities();
 
 4124   if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
 
 4129     if ( !( drvName == QLatin1String( 
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
 
 4132   if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
 
 4136   int layer_count = OGR_DS_GetLayerCount( hDS.get() );
 
 4139     OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 4142       if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
 
 4145         if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
 
 4156     const QString &layerNameIn )
 
 4158   OGRSFDriverH hDriver = 
nullptr;
 
 4163   QString layerName( layerNameIn );
 
 4164   if ( layerName.isEmpty() )
 
 4165     layerName = QFileInfo( datasetName ).baseName();
 
 4167   return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
 
 4172     const QString &layerName,
 
 4176   OGRSFDriverH hDriver = 
nullptr;
 
 4180   OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
 
 4186   OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
 
 4187   const auto constAttributes = attributes;
 
 4188   for ( 
int idx : constAttributes )
 
 4191     if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
 
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.
 
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.
 
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
 
This class 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.
 
Q_GADGET QgsUnitTypes::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.
 
Class for storing the component parts of a RDBMS 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)
 
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
 
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.
 
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
 
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
 
This class 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.
 
@ 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.
 
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 SIP_HOLDGIL
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
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.
 
QVariant::Type subType() const
If the field is a collection, gets its element's type.
 
Container of fields for a vector layer.
 
int count() const
Returns number of items.
 
int size() const
Returns number of items.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
A geometry is the spatial representation of a feature.
 
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
 
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
 
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
 
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
 
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
 
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
 
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
 
static void warning(const QString &msg)
Goes to qWarning.
 
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)
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.
 
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) SIP_THROW(QgsNotSupportedException)
Saves metadata to the layer corresponding to the specified uri.
 
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
 
void changeMode(Mode mode)
Change the mode of the lock to mode.
 
A rectangle specified with double values.
 
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
 
Contains information about the context of a rendering operation.
 
QgsExpressionContext & expressionContext()
Gets the expression context.
 
void setRendererScale(double scale)
Sets the renderer map scale.
 
This class is a composition of two QSettings instances:
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
 
int layer() const
The layer of this symbol level.
 
QgsSymbol * symbol() const
The symbol of this symbol level.
 
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.
 
DistanceUnit
Units of distance.
 
RenderUnit
Rendering size units.
 
@ RenderMillimeters
Millimeters.
 
@ RenderMapUnits
Map units.
 
Interface to convert raw field values to their user-friendly value.
 
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.
 
QgsVectorFileWriter::OptionType type
 
Options to pass to writeAsVectorFormat()
 
QString fileEncoding
Encoding to use.
 
bool forceMulti
Sets to true to force creation of multi* geometries.
 
FieldNameSource fieldNameSource
Source for exported field names.
 
QString driverName
OGR driver to use.
 
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
 
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
 
SaveVectorOptions()
Constructor.
 
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.
 
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
 
QStringList layerOptions
List of OGR layer creation options.
 
QgsVectorFileWriter::SymbologyExport symbologyExport
Symbology to export.
 
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
 
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.
 
bool skipAttributeCreation
Only write geometries.
 
double symbologyScale
Scale of symbology.
 
QStringList datasourceOptions
List of OGR data source creation options.
 
QgsWkbTypes::Type overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
 
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
 
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.
 
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.
 
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, QgsWkbTypes::Type 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.
 
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.
 
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)
 
OGRGeometryH createEmptyGeometry(QgsWkbTypes::Type wkbType)
 
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.
 
~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.
 
SymbologyExport mSymbologyExport
 
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
 
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)
 
QgsVectorFileWriter::WriterError hasError()
Checks whether there were any errors in constructor.
 
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
 
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
 
QgsWkbTypes::Type mWkbType
Geometry type which is being used.
 
static OGRwkbGeometryType ogrTypeFromWkbType(QgsWkbTypes::Type type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
 
@ 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.
 
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, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, QgsWkbTypes::Type overrideGeometryType=QgsWkbTypes::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
 
WriterError mError
Contains error value if construction was not successful.
 
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.
 
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
 
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
 
QString errorMessage()
Retrieves error message.
 
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.
 
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, QgsUnitTypes::DistanceUnit outputUnit=QgsUnitTypes::DistanceMeters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
 
QgsVectorFileWriter::SymbologyExport symbologyExport() const
 
void setSymbologyScale(double scale)
Set reference scale for output.
 
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, QgsVectorFileWriter::SymbologyExport symbologyExport=QgsVectorFileWriter::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
 
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
 
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
 
ActionOnExistingFile
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
 
@ 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 data sets.
 
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
 
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.
 
QgsFields fields() const FINAL
Returns the list of fields of this layer.
 
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.
 
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.
 
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
 
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
 
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
 
Type
The WKB type describes the number of dimensions a geometry has.
 
static Type to25D(Type type) SIP_HOLDGIL
Will convert the 25D version of the flat type if supported or Unknown if not supported.
 
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
 
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
 
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
 
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
 
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
 
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)
 
QList< QgsSymbolLevel > QgsSymbolLevelOrder
 
QList< QgsSymbolLevelItem > QgsSymbolLevel
 
QList< QgsSymbol * > QgsSymbolList
 
Details of available driver formats.
 
QString longName
Descriptive, user friendly name for the driver.
 
QString driverName
Unique driver name.