47#include <QRegularExpression> 
   48#include <QJsonDocument> 
   54#include <ogr_srs_api.h> 
   57#include <cpl_string.h> 
   76    const QString &fileEncoding,
 
   80    const QString &driverName,
 
   81    const QStringList &datasourceOptions,
 
   82    const QStringList &layerOptions,
 
   94  init( vectorFileName, fileEncoding, fields,  geometryType,
 
   95        srs, driverName, datasourceOptions, layerOptions, newFilename, 
nullptr,
 
 
  100    const QString &fileEncoding,
 
  104    const QString &driverName,
 
  105    const QStringList &datasourceOptions,
 
  106    const QStringList &layerOptions,
 
  107    QString *newFilename,
 
  110    const QString &layerName,
 
  116    bool includeConstraints,
 
  117    bool setFieldDomains,
 
  120  , mWkbType( geometryType )
 
  121  , mSymbologyExport( symbologyExport )
 
  122  , mSymbologyScale( 1.0 )
 
  123  , mIncludeConstraints( includeConstraints )
 
  124  , mSetFieldDomains( setFieldDomains )
 
  126  init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
 
  127        datasourceOptions, layerOptions, newFilename, fieldValueConverter,
 
  128        layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource, sourceDatabaseProviderConnection );
 
 
  132  const QString &fileName,
 
  139  QString *newFilename,
 
 
  153  if ( driverName == QLatin1String( 
"MapInfo MIF" ) )
 
  157  GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
 
  165#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0) 
  166  return CSLFetchBoolean( 
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE, 
false );
 
  168  return CSLFetchBoolean( 
driverMetadata, GDAL_DCAP_FEATURE_STYLES, 
false );
 
 
  172void QgsVectorFileWriter::init( QString vectorFileName,
 
  173                                QString fileEncoding,
 
  177                                const QString &driverName,
 
  178                                QStringList datasourceOptions,
 
  179                                QStringList layerOptions,
 
  180                                QString *newFilename,
 
  181                                FieldValueConverter *fieldValueConverter,
 
  182                                const QString &layerNameIn,
 
  183                                ActionOnExistingFile action,
 
  184                                QString *newLayer, SinkFlags sinkFlags,
 
  188#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,5,0) 
  189  ( void )sourceDatabaseProviderConnection;
 
  194  if ( vectorFileName.isEmpty() )
 
  201  if ( driverName == QLatin1String( 
"MapInfo MIF" ) )
 
  205  else if ( driverName == QLatin1String( 
"SpatiaLite" ) )
 
  208    if ( !datasourceOptions.contains( QStringLiteral( 
"SPATIALITE=YES" ) ) )
 
  210      datasourceOptions.append( QStringLiteral( 
"SPATIALITE=YES" ) );
 
  213  else if ( driverName == QLatin1String( 
"DBF file" ) )
 
  216    if ( !layerOptions.contains( QStringLiteral( 
"SHPT=NULL" ) ) )
 
  218      layerOptions.append( QStringLiteral( 
"SHPT=NULL" ) );
 
  227#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1) 
  228  QString fidFieldName;
 
  231    for ( 
const QString &layerOption : layerOptions )
 
  233      if ( layerOption.startsWith( QLatin1String( 
"FID=" ) ) )
 
  235        fidFieldName = layerOption.mid( 4 );
 
  239    if ( fidFieldName.isEmpty() )
 
  240      fidFieldName = QStringLiteral( 
"fid" );
 
  245  OGRSFDriverH poDriver;
 
  248  poDriver = OGRGetDriverByName( 
mOgrDriverName.toLocal8Bit().constData() );
 
  252    mErrorMessage = QObject::tr( 
"OGR driver for '%1' not found (OGR error: %2)" )
 
  254                          QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  259  mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME, 
nullptr ) );
 
  266    if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String( 
"ENCODING=" ) ) == -1 )
 
  271    if ( driverName == QLatin1String( 
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String( 
".shp" ), Qt::CaseInsensitive ) )
 
  273      vectorFileName += QLatin1String( 
".shp" );
 
  275    else if ( driverName == QLatin1String( 
"DBF file" ) && !vectorFileName.endsWith( QLatin1String( 
".dbf" ), Qt::CaseInsensitive ) )
 
  277      vectorFileName += QLatin1String( 
".dbf" );
 
  287      QStringList allExts = metadata.glob.split( 
' ', Qt::SkipEmptyParts );
 
  289      const auto constAllExts = allExts;
 
  290      for ( 
const QString &ext : constAllExts )
 
  293        if ( vectorFileName.endsWith( ext.mid( 1 ), Qt::CaseInsensitive ) )
 
  302        allExts = metadata.ext.split( 
' ', Qt::SkipEmptyParts );
 
  303        vectorFileName += 
'.' + allExts[0];
 
  309      if ( vectorFileName.endsWith( QLatin1String( 
".gdb" ), Qt::CaseInsensitive ) )
 
  311        QDir dir( vectorFileName );
 
  314          QFileInfoList fileList = dir.entryInfoList(
 
  315                                     QDir::NoDotAndDotDot | QDir::System | QDir::Hidden  | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
 
  316          const auto constFileList = fileList;
 
  317          for ( 
const QFileInfo &info : constFileList )
 
  319            QFile::remove( info.absoluteFilePath() );
 
  322        QDir().rmdir( vectorFileName );
 
  326        QFile::remove( vectorFileName );
 
  331  if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
 
  333    if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
 
  335      QgsDebugMsgLevel( QStringLiteral( 
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
 
  336      fileEncoding = metadata.compulsoryEncoding;
 
  341  char **options = 
nullptr;
 
  342  if ( !datasourceOptions.isEmpty() )
 
  344    options = 
new char *[ datasourceOptions.size() + 1 ];
 
  345    for ( 
int i = 0; i < datasourceOptions.size(); i++ )
 
  347      QgsDebugMsgLevel( QStringLiteral( 
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
 
  348      options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
 
  350    options[ datasourceOptions.size()] = 
nullptr;
 
  357    mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
 
  359    mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE, 
nullptr ) );
 
  363    for ( 
int i = 0; i < datasourceOptions.size(); i++ )
 
  364      CPLFree( options[i] );
 
  373      mErrorMessage = QObject::tr( 
"Creation of data source failed (OGR error: %1)" )
 
  374                      .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  376      mErrorMessage = QObject::tr( 
"Opening of data source in update mode failed (OGR error: %1)" )
 
  377                      .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  381  QString layerName( layerNameIn );
 
  382  if ( layerName.isEmpty() )
 
  383    layerName = QFileInfo( vectorFileName ).baseName();
 
  387    const int layer_count = OGR_DS_GetLayerCount( 
mDS.get() );
 
  388    for ( 
int i = 0; i < layer_count; i++ )
 
  390      OGRLayerH hLayer = OGR_DS_GetLayer( 
mDS.get(), i );
 
  391      if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
 
  393        if ( OGR_DS_DeleteLayer( 
mDS.get(), i ) != OGRERR_NONE )
 
  396          mErrorMessage = QObject::tr( 
"Overwriting of existing layer failed (OGR error: %1)" )
 
  397                          .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  411    QgsDebugMsgLevel( QStringLiteral( 
"Opened data source in update mode" ), 2 );
 
  415  mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
 
  418    QgsDebugError( 
"error finding QTextCodec for " + fileEncoding );
 
  421    QString enc = settings.
value( QStringLiteral( 
"UI/encoding" ), 
"System" ).toString();
 
  422    mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
 
  426      mCodec = QTextCodec::codecForLocale();
 
  432  if ( driverName == QLatin1String( 
"KML" ) || driverName == QLatin1String( 
"LIBKML" ) || driverName == QLatin1String( 
"GPX" ) )
 
  434    if ( srs.
authid() != QLatin1String( 
"EPSG:4326" ) )
 
  449  int optIndex = layerOptions.indexOf( QLatin1String( 
"FEATURE_DATASET=" ) );
 
  450  if ( optIndex != -1 )
 
  452    layerOptions.removeAt( optIndex );
 
  455  if ( !layerOptions.isEmpty() )
 
  457    options = 
new char *[ layerOptions.size() + 1 ];
 
  458    for ( 
int i = 0; i < layerOptions.size(); i++ )
 
  461      options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
 
  463    options[ layerOptions.size()] = 
nullptr;
 
  467  CPLSetConfigOption( 
"SHAPE_ENCODING", 
"" );
 
  471    mLayer = OGR_DS_CreateLayer( 
mDS.get(), layerName.toUtf8().constData(), 
mOgrRef, wkbType, options );
 
  474      *newLayer = OGR_L_GetName( 
mLayer );
 
  475      if ( driverName == QLatin1String( 
"GPX" ) )
 
  482            if ( !EQUAL( layerName.toUtf8().constData(), 
"track_points" ) &&
 
  483                 !EQUAL( layerName.toUtf8().constData(), 
"route_points" ) )
 
  485              *newLayer = QStringLiteral( 
"waypoints" );
 
  492            const char *pszForceGPXTrack
 
  493              = CSLFetchNameValue( options, 
"FORCE_GPX_TRACK" );
 
  494            if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
 
  495              *newLayer = QStringLiteral( 
"tracks" );
 
  497              *newLayer = QStringLiteral( 
"routes" );
 
  504            const char *pszForceGPXRoute
 
  505              = CSLFetchNameValue( options, 
"FORCE_GPX_ROUTE" );
 
  506            if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
 
  507              *newLayer = QStringLiteral( 
"routes" );
 
  509              *newLayer = QStringLiteral( 
"tracks" );
 
  519  else if ( driverName == QLatin1String( 
"DGN" ) )
 
  521    mLayer = OGR_DS_GetLayerByName( 
mDS.get(), 
"elements" );
 
  525    mLayer = OGR_DS_GetLayerByName( 
mDS.get(), layerName.toUtf8().constData() );
 
  530    for ( 
int i = 0; i < layerOptions.size(); i++ )
 
  531      CPLFree( options[i] );
 
  540      QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String( 
".shp" ), Qt::CaseInsensitive ) );
 
  541      QFile prjFile( layerName + 
".qpj" );
 
  542      if ( prjFile.exists() )
 
  550      mErrorMessage = QObject::tr( 
"Creation of layer failed (OGR error: %1)" )
 
  551                      .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  553      mErrorMessage = QObject::tr( 
"Opening of layer failed (OGR error: %1)" )
 
  554                      .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  559  OGRFeatureDefnH defn = OGR_L_GetLayerDefn( 
mLayer );
 
  568  QSet<int> existingIdxs;
 
  572#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0) 
  573  if ( 
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS, 
nullptr ) )
 
  575    char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags, 
" ", 0 );
 
  576    if ( CSLFindString( papszTokens, 
"AlternativeName" ) >= 0 )
 
  580    if ( CSLFindString( papszTokens, 
"Comment" ) >= 0 )
 
  584    CSLDestroy( papszTokens );
 
  594#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0) 
  595      QSet<QString> existingDestDomainNames;
 
  596      if ( sourceDatabaseProviderConnection )
 
  598        char **domainNames = GDALDatasetGetFieldDomainNames( 
mDS.get(), 
nullptr );
 
  599        for ( 
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
 
  601          existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
 
  603        CSLDestroy( domainNames );
 
  606#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
  607      QSet< QString > usedAlternativeNames;
 
  610      const QString ogrFidColumnName { OGR_L_GetFIDColumn( 
mLayer ) };
 
  611      const int fidNameIndex = OGR_FD_GetFieldIndex( defn, ogrFidColumnName.toUtf8() );
 
  614      const bool promoteFidColumnToAttribute = !ogrFidColumnName.isEmpty() && fidNameIndex < 0 && fields.
lookupField( ogrFidColumnName ) >= 0;
 
  615      int offsetRoomForFid = promoteFidColumnToAttribute ? 1 : 0;
 
  617      for ( 
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
 
  621        if ( fieldValueConverter )
 
  623          attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
 
  628          int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( attrField.
name() ) );
 
  637        switch ( fieldNameSource )
 
  640            name = attrField.
name();
 
  644            name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
 
  648        OGRFieldType ogrType = OFTString; 
 
  649        OGRFieldSubType ogrSubType = OFSTNone;
 
  650        int ogrWidth = attrField.
length();
 
  651        int ogrPrecision = attrField.
precision();
 
  652        if ( ogrPrecision > 0 )
 
  655        switch ( attrField.
type() )
 
  657          case QMetaType::Type::LongLong:
 
  659            const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  660            if ( pszDataTypes && strstr( pszDataTypes, 
"Integer64" ) )
 
  661              ogrType = OFTInteger64;
 
  664            ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
 
  668          case QMetaType::Type::QString:
 
  670            if ( ( ogrWidth <= 0 || ogrWidth > 255 ) && 
mOgrDriverName == QLatin1String( 
"ESRI Shapefile" ) )
 
  674          case QMetaType::Type::Int:
 
  675            ogrType = OFTInteger;
 
  676            ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
 
  680          case QMetaType::Type::Bool:
 
  681            ogrType = OFTInteger;
 
  682            ogrSubType = OFSTBoolean;
 
  687          case QMetaType::Type::Double:
 
  688#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1) 
  689            if ( 
mOgrDriverName == QLatin1String( 
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
 
  692              ogrType = OFTInteger64;
 
  699          case QMetaType::Type::QDate:
 
  703          case QMetaType::Type::QTime:
 
  715          case QMetaType::Type::QDateTime:
 
  723              ogrType = OFTDateTime;
 
  727          case QMetaType::Type::QByteArray:
 
  731          case QMetaType::Type::QStringList:
 
  737              ogrSubType = OFSTJSON;
 
  741            const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  742            if ( pszDataTypes && strstr( pszDataTypes, 
"StringList" ) )
 
  744              ogrType = OFTStringList;
 
  745              mSupportedListSubTypes.insert( QMetaType::Type::QString );
 
  755          case QMetaType::Type::QVariantMap:
 
  758            const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES, 
nullptr );
 
  759            if ( pszDataSubTypes && strstr( pszDataSubTypes, 
"JSON" ) )
 
  762              ogrSubType = OFSTJSON;
 
  770          case QMetaType::Type::QVariantList:
 
  775              ogrSubType = OFSTJSON;
 
  780            if ( attrField.
subType() == QMetaType::Type::QString )
 
  782              const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  783              if ( pszDataTypes && strstr( pszDataTypes, 
"StringList" ) )
 
  785                ogrType = OFTStringList;
 
  786                mSupportedListSubTypes.insert( QMetaType::Type::QString );
 
  795            else if ( attrField.
subType() == QMetaType::Type::Int )
 
  797              const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  798              if ( pszDataTypes && strstr( pszDataTypes, 
"IntegerList" ) )
 
  800                ogrType = OFTIntegerList;
 
  801                mSupportedListSubTypes.insert( QMetaType::Type::Int );
 
  810            else if ( attrField.
subType() == QMetaType::Type::Double )
 
  812              const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  813              if ( pszDataTypes && strstr( pszDataTypes, 
"RealList" ) )
 
  815                ogrType = OFTRealList;
 
  816                mSupportedListSubTypes.insert( QMetaType::Type::Double );
 
  825            else if ( attrField.
subType() == QMetaType::Type::LongLong )
 
  827              const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr );
 
  828              if ( pszDataTypes && strstr( pszDataTypes, 
"Integer64List" ) )
 
  830                ogrType = OFTInteger64List;
 
  831                mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
 
  845            mErrorMessage = QObject::tr( 
"Unsupported type for field %1" )
 
  846                            .arg( attrField.
name() );
 
  851        if ( 
mOgrDriverName == QLatin1String( 
"SQLite" ) && name.compare( QLatin1String( 
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
 
  854          for ( i = 0; i < 10; i++ )
 
  856            name = QStringLiteral( 
"ogc_fid%1" ).arg( i );
 
  859            for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
 
  862            if ( j == fields.
size() )
 
  868            mErrorMessage = QObject::tr( 
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
 
  873          QgsMessageLog::logMessage( QObject::tr( 
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr( 
"OGR" ) );
 
  880          OGR_Fld_SetWidth( fld.get(), ogrWidth );
 
  883        if ( ogrPrecision >= 0 )
 
  885          OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
 
  888        if ( ogrSubType != OFSTNone )
 
  889          OGR_Fld_SetSubType( fld.get(), ogrSubType );
 
  891#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
  892        if ( !attrField.
alias().isEmpty() )
 
  894          QString alternativeName = attrField.
alias();
 
  896          while ( usedAlternativeNames.contains( alternativeName ) )
 
  899            alternativeName = attrField.
alias() + QStringLiteral( 
" (%1)" ).arg( ++counter );
 
  901          OGR_Fld_SetAlternativeName( fld.get(), 
mCodec->fromUnicode( alternativeName ).constData() );
 
  902          usedAlternativeNames.insert( alternativeName );
 
  905#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0) 
  906        OGR_Fld_SetComment( fld.get(), 
mCodec->fromUnicode( attrField.
comment() ).constData() );
 
  913            OGR_Fld_SetNullable( fld.get(), 
false );
 
  917            OGR_Fld_SetUnique( fld.get(), 
true );
 
  920#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0) 
  924          if ( !domainName.isEmpty() )
 
  926            bool canSetFieldDomainName = 
false;
 
  927            if ( existingDestDomainNames.contains( domainName ) )
 
  931              canSetFieldDomainName = 
true;
 
  933            else  if ( GDALDatasetTestCapability( 
mDS.get(), ODsCAddFieldDomain ) )
 
  943                std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
 
  949                    char *pszFailureReason = 
nullptr;
 
  950                    if ( GDALDatasetAddFieldDomain( 
mDS.get(), hFieldDomain, &pszFailureReason ) )
 
  952                      existingDestDomainNames.insert( domainName );
 
  953                      canSetFieldDomainName = 
true;
 
  957                      QgsDebugError( QStringLiteral( 
"cannot create field domain: %1" ).arg( pszFailureReason ) );
 
  959                    CPLFree( pszFailureReason );
 
  960                    OGR_FldDomain_Destroy( hFieldDomain );
 
  966                QgsDebugError( QStringLiteral( 
"Cannot retrieve field domain: %1" ).arg( domainName ) );
 
  969            if ( canSetFieldDomainName )
 
  971              OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
 
  979                          " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
 
  980                          " width " + QString::number( ogrWidth ) +
 
  981                          " precision " + QString::number( ogrPrecision ), 2 );
 
  982        if ( OGR_L_CreateField( 
mLayer, fld.get(), 
true ) != OGRERR_NONE )
 
  985          mErrorMessage = QObject::tr( 
"Creation of field %1 (%2) failed (OGR error: %3)" )
 
  986                          .arg( attrField.
name(),
 
  987                                QVariant::typeToName( attrField.
type() ),
 
  988                                QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
  993        int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( name ) );
 
  994        QgsDebugMsgLevel( QStringLiteral( 
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
 
  995        if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
 
  998          ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
 
 1003            mErrorMessage = QObject::tr( 
"Created field %1 not found (OGR error: %2)" )
 
 1004                            .arg( attrField.
name(),
 
 1005                                  QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 1011        if ( promoteFidColumnToAttribute )
 
 1013          if ( ogrFidColumnName.compare( attrField.
name(), Qt::CaseInsensitive ) == 0 )
 
 1016            offsetRoomForFid = 0;
 
 1021            ogrIdx += offsetRoomForFid;
 
 1025        existingIdxs.insert( ogrIdx );
 
 1033      for ( 
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
 
 1036        QString name( attrField.
name() );
 
 1037        int ogrIdx = OGR_FD_GetFieldIndex( defn, 
mCodec->fromUnicode( name ) );
 
 1049    int fidIdx = fields.
lookupField( QStringLiteral( 
"FID" ) );
 
 1060    *newFilename = vectorFileName;
 
 1063  mUsingTransaction = 
true;
 
 1064  if ( OGRERR_NONE != OGR_L_StartTransaction( 
mLayer ) )
 
 1066    mUsingTransaction = 
false;
 
 1076class QgsVectorFileWriterMetadataContainer
 
 1080    QgsVectorFileWriterMetadataContainer()
 
 1082      QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
 
 1083      QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
 
 1086      datasetOptions.clear();
 
 1087      layerOptions.clear();
 
 1090                             QObject::tr( 
"Compression method." ),
 
 1092                             << QStringLiteral( 
"UNCOMPRESSED" )
 
 1093                             << QStringLiteral( 
"ZSTD" )
 
 1094                             << QStringLiteral( 
"LZ4" ),
 
 1095                             QStringLiteral( 
"LZ4" ), 
 
 1100                             QObject::tr( 
"Geometry encoding." ),
 
 1102                             << QStringLiteral( 
"GEOARROW" )
 
 1103                             << QStringLiteral( 
"WKB" )
 
 1104                             << QStringLiteral( 
"WKT" ),
 
 1105                             QStringLiteral( 
"GEOARROW" ), 
 
 1110                             QObject::tr( 
"Maximum number of rows per batch." ),
 
 1115                             QObject::tr( 
"Name for the feature identifier column" ),
 
 1120                             QObject::tr( 
"Name for the geometry column" ),
 
 1121                             QStringLiteral( 
"geometry" )  
 
 1124      driverMetadata.insert( QStringLiteral( 
"Arrow" ),
 
 1126                               QStringLiteral( 
"(Geo)Arrow" ),
 
 1127                               QObject::tr( 
"(Geo)Arrow" ),
 
 1128                               QStringLiteral( 
"*.arrow *.feather *.arrows *.ipc" ),
 
 1129                               QStringLiteral( 
"arrow" ),
 
 1132                               QStringLiteral( 
"UTF-8" )
 
 1137      datasetOptions.clear();
 
 1138      layerOptions.clear();
 
 1140      driverMetadata.insert( QStringLiteral( 
"AVCE00" ),
 
 1142                               QStringLiteral( 
"Arc/Info ASCII Coverage" ),
 
 1143                               QObject::tr( 
"Arc/Info ASCII Coverage" ),
 
 1144                               QStringLiteral( 
"*.e00" ),
 
 1145                               QStringLiteral( 
"e00" ),
 
 1152      datasetOptions.clear();
 
 1153      layerOptions.clear();
 
 1156                             QObject::tr( 
"By default when creating new .csv files they " 
 1157                                          "are created with the line termination conventions " 
 1158                                          "of the local platform (CR/LF on Win32 or LF on all other systems). " 
 1159                                          "This may be overridden through the use of the LINEFORMAT option." ),
 
 1161                             << QStringLiteral( 
"CRLF" )
 
 1162                             << QStringLiteral( 
"LF" ),
 
 1168                             QObject::tr( 
"By default, the geometry of a feature written to a .csv file is discarded. " 
 1169                                          "It is possible to export the geometry in its WKT representation by " 
 1170                                          "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries " 
 1171                                          "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY " 
 1172                                          "or GEOMETRY=AS_YX." ),
 
 1174                             << QStringLiteral( 
"AS_WKT" )
 
 1175                             << QStringLiteral( 
"AS_XYZ" )
 
 1176                             << QStringLiteral( 
"AS_XY" )
 
 1177                             << QStringLiteral( 
"AS_YX" ),
 
 1183                             QObject::tr( 
"Name of geometry column. Only used if GEOMETRY=AS_WKT. Defaults to 'WKT'." ),
 
 1184                             QStringLiteral( 
"WKT" )  
 
 1188                             QObject::tr( 
"Create the associated .csvt file to describe the type of each " 
 1189                                          "column of the layer and its optional width and precision. " 
 1190                                          "This option also creates a .prj file which stores coordinate system information." ),
 
 1195                             QObject::tr( 
"Field separator character." ),
 
 1197                             << QStringLiteral( 
"COMMA" )
 
 1198                             << QStringLiteral( 
"SEMICOLON" )
 
 1199                             << QStringLiteral( 
"TAB" )
 
 1200                             << QStringLiteral( 
"SPACE" )
 
 1201#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,12,0)
 
 1202                             << QStringLiteral( 
"PIPE" )
 
 1204                             , QStringLiteral( 
"COMMA" ) 
 
 1208                             QObject::tr( 
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
 
 1210                             << QStringLiteral( 
"IF_NEEDED" )
 
 1211                             << QStringLiteral( 
"IF_AMBIGUOUS" )
 
 1212                             << QStringLiteral( 
"ALWAYS" ),
 
 1213                             QStringLiteral( 
"IF_AMBIGUOUS" ) 
 
 1217                             QObject::tr( 
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
 
 1221#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,12,0) 
 1223                             QObject::tr( 
"Whether to write a header line with the field names." ),
 
 1228      driverMetadata.insert( QStringLiteral( 
"CSV" ),
 
 1230                               QStringLiteral( 
"Comma Separated Value [CSV]" ),
 
 1231                               QObject::tr( 
"Comma Separated Value [CSV]" ),
 
 1232                               QStringLiteral( 
"*.csv" ),
 
 1233                               QStringLiteral( 
"csv" ),
 
 1240      datasetOptions.clear();
 
 1241      layerOptions.clear();
 
 1243      driverMetadata.insert( QStringLiteral( 
"FlatGeobuf" ),
 
 1245                               QStringLiteral( 
"FlatGeobuf" ),
 
 1246                               QObject::tr( 
"FlatGeobuf" ),
 
 1247                               QStringLiteral( 
"*.fgb" ),
 
 1248                               QStringLiteral( 
"fgb" ),
 
 1251                               QStringLiteral( 
"UTF-8" )
 
 1256      datasetOptions.clear();
 
 1257      layerOptions.clear();
 
 1260                             QObject::tr( 
"Override the type of shapefile created. " 
 1261                                          "Can be one of NULL for a simple .dbf file with no .shp file, POINT, " 
 1262                                          "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or " 
 1263                                          "MULTIPOINTZ for 3D;" ) +
 
 1264                             QObject::tr( 
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries" 
 1265                                          " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured" 
 1267                             QObject::tr( 
" MULTIPATCH files are supported since GDAL 2.2." ) +
 
 1270                             << QStringLiteral( 
"NULL" )
 
 1271                             << QStringLiteral( 
"POINT" )
 
 1272                             << QStringLiteral( 
"ARC" )
 
 1273                             << QStringLiteral( 
"POLYGON" )
 
 1274                             << QStringLiteral( 
"MULTIPOINT" )
 
 1275                             << QStringLiteral( 
"POINTZ" )
 
 1276                             << QStringLiteral( 
"ARCZ" )
 
 1277                             << QStringLiteral( 
"POLYGONZ" )
 
 1278                             << QStringLiteral( 
"MULTIPOINTZ" )
 
 1279                             << QStringLiteral( 
"POINTM" )
 
 1280                             << QStringLiteral( 
"ARCM" )
 
 1281                             << QStringLiteral( 
"POLYGONM" )
 
 1282                             << QStringLiteral( 
"MULTIPOINTM" )
 
 1283                             << QStringLiteral( 
"POINTZM" )
 
 1284                             << QStringLiteral( 
"ARCZM" )
 
 1285                             << QStringLiteral( 
"POLYGONZM" )
 
 1286                             << QStringLiteral( 
"MULTIPOINTZM" )
 
 1287                             << QStringLiteral( 
"MULTIPATCH" )
 
 1297                             QObject::tr( 
"Set the encoding value in the DBF file. " 
 1298                                          "The default value is LDID/87. It is not clear " 
 1299                                          "what other values may be appropriate." ),
 
 1307                             QObject::tr( 
"Set to YES to resize fields to their optimal size." ),
 
 1311      driverMetadata.insert( QStringLiteral( 
"ESRI" ),
 
 1313                               QStringLiteral( 
"ESRI Shapefile" ),
 
 1314                               QObject::tr( 
"ESRI Shapefile" ),
 
 1315                               QStringLiteral( 
"*.shp" ),
 
 1316                               QStringLiteral( 
"shp" ),
 
 1323      datasetOptions.clear();
 
 1324      layerOptions.clear();
 
 1326      driverMetadata.insert( QStringLiteral( 
"DBF File" ),
 
 1328                               QStringLiteral( 
"DBF File" ),
 
 1329                               QObject::tr( 
"DBF File" ),
 
 1330                               QStringLiteral( 
"*.dbf" ),
 
 1331                               QStringLiteral( 
"dbf" ),
 
 1338      datasetOptions.clear();
 
 1339      layerOptions.clear();
 
 1342                             QObject::tr( 
"Set to YES to write a bbox property with the bounding box " 
 1343                                          "of the geometries at the feature and feature collection level." ),
 
 1348                             QObject::tr( 
"Maximum number of figures after decimal separator to write in coordinates. " 
 1349                                          "Defaults to 15. Truncation will occur to remove trailing zeros." ),
 
 1354                             QObject::tr( 
"Whether to use RFC 7946 standard. " 
 1355                                          "If disabled GeoJSON 2008 initial version will be used. " 
 1356                                          "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
 
 1360      driverMetadata.insert( QStringLiteral( 
"GeoJSON" ),
 
 1362                               QStringLiteral( 
"GeoJSON" ),
 
 1363                               QObject::tr( 
"GeoJSON" ),
 
 1364                               QStringLiteral( 
"*.geojson" ),
 
 1365                               QStringLiteral( 
"geojson" ),
 
 1368                               QStringLiteral( 
"UTF-8" )
 
 1373      datasetOptions.clear();
 
 1374      layerOptions.clear();
 
 1377                             QObject::tr( 
"Maximum number of figures after decimal separator to write in coordinates. " 
 1378                                          "Defaults to 15. Truncation will occur to remove trailing zeros." ),
 
 1383                             QObject::tr( 
"Whether to start records with the RS=0x1E character (RFC 8142 standard). " 
 1384                                          "Defaults to NO: Newline Delimited JSON (geojsonl). \n" 
 1385                                          "If set to YES:  RFC 8142 standard: GeoJSON Text Sequences  (geojsons)." ),
 
 1389      driverMetadata.insert( QStringLiteral( 
"GeoJSONSeq" ),
 
 1391                               QStringLiteral( 
"GeoJSON - Newline Delimited" ),
 
 1392                               QObject::tr( 
"GeoJSON - Newline Delimited" ),
 
 1393                               QStringLiteral( 
"*.geojsonl *.geojsons *.json" ),
 
 1394                               QStringLiteral( 
"geojsonl geojsons json" ),
 
 1397                               QStringLiteral( 
"UTF-8" )
 
 1402      datasetOptions.clear();
 
 1403      layerOptions.clear();
 
 1406                               QObject::tr( 
"whether the document must be in RSS 2.0 or Atom 1.0 format. " 
 1407                                            "Default value : RSS" ),
 
 1409                               << QStringLiteral( 
"RSS" )
 
 1410                               << QStringLiteral( 
"ATOM" ),
 
 1411                               QStringLiteral( 
"RSS" ) 
 
 1415                               QObject::tr( 
"The encoding of location information. Default value : SIMPLE. " 
 1416                                            "W3C_GEO only supports point geometries. " 
 1417                                            "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
 
 1419                               << QStringLiteral( 
"SIMPLE" )
 
 1420                               << QStringLiteral( 
"GML" )
 
 1421                               << QStringLiteral( 
"W3C_GEO" ),
 
 1422                               QStringLiteral( 
"SIMPLE" ) 
 
 1426                               QObject::tr( 
"If defined to YES, extension fields will be written. " 
 1427                                            "If the field name not found in the base schema matches " 
 1428                                            "the foo_bar pattern, foo will be considered as the namespace " 
 1429                                            "of the element, and a <foo:bar> element will be written. " 
 1430                                            "Otherwise, elements will be written in the <ogr:> namespace." ),
 
 1435                               QObject::tr( 
"If defined to NO, only <entry> or <item> elements will be written. " 
 1436                                            "The user will have to provide the appropriate header and footer of the document." ),
 
 1441                               QObject::tr( 
"XML content that will be put between the <channel> element and the " 
 1442                                            "first <item> element for a RSS document, or between the xml tag and " 
 1443                                            "the first <entry> element for an Atom document." ),
 
 1448                               QObject::tr( 
"Value put inside the <title> element in the header. " 
 1449                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1454                               QObject::tr( 
"Value put inside the <description> element in the header. " 
 1455                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1460                               QObject::tr( 
"Value put inside the <link> element in the header. " 
 1461                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1466                               QObject::tr( 
"Value put inside the <updated> element in the header. " 
 1467                                            "Should be formatted as a XML datetime. " 
 1468                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1473                               QObject::tr( 
"Value put inside the <author><name> element in the header. " 
 1474                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1479                               QObject::tr( 
"Value put inside the <id> element in the header. " 
 1480                                            "If not provided, a dummy value will be used as that element is compulsory." ),
 
 1484      driverMetadata.insert( QStringLiteral( 
"GeoRSS" ),
 
 1486                               QStringLiteral( 
"GeoRSS" ),
 
 1487                               QObject::tr( 
"GeoRSS" ),
 
 1488                               QStringLiteral( 
"*.xml" ),
 
 1489                               QStringLiteral( 
"xml" ),
 
 1492                               QStringLiteral( 
"UTF-8" )
 
 1497      datasetOptions.clear();
 
 1498      layerOptions.clear();
 
 1501                               QObject::tr( 
"If provided, this URI will be inserted as the schema location. " 
 1502                                            "Note that the schema file isn't actually accessed by OGR, so it " 
 1503                                            "is up to the user to ensure it will match the schema of the OGR " 
 1504                                            "produced GML data file." ),
 
 1509                               QObject::tr( 
"This writes a GML application schema file to a corresponding " 
 1510                                            ".xsd file (with the same basename). If INTERNAL is used the " 
 1511                                            "schema is written within the GML file, but this is experimental " 
 1512                                            "and almost certainly not valid XML. " 
 1513                                            "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
 
 1515                               << QStringLiteral( 
"EXTERNAL" )
 
 1516                               << QStringLiteral( 
"INTERNAL" )
 
 1517                               << QStringLiteral( 
"OFF" ),
 
 1518                               QStringLiteral( 
"EXTERNAL" ) 
 
 1522                               QObject::tr( 
"This is the prefix for the application target namespace." ),
 
 1523                               QStringLiteral( 
"ogr" )  
 
 1527                               QObject::tr( 
"Can be set to TRUE to avoid writing the prefix of the " 
 1528                                            "application target namespace in the GML file." ),
 
 1533                               QObject::tr( 
"Defaults to 'http://ogr.maptools.org/'. " 
 1534                                            "This is the application target namespace." ),
 
 1535                               QStringLiteral( 
"http://ogr.maptools.org/" )  
 
 1539                               QObject::tr( 
"GML version to use." ),
 
 1541                               << QStringLiteral( 
"GML2" )
 
 1542                               << QStringLiteral( 
"GML3" )
 
 1543                               << QStringLiteral( 
"GML3Deegree" )
 
 1544                               << QStringLiteral( 
"GML3.2" ),
 
 1545                               QStringLiteral( 
"GML3.2" ) 
 
 1549                               QObject::tr( 
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "  
 1550                                            "If YES, SRS with EPSG authority will be written with the " 
 1551                                            "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a " 
 1552                                            "geographic SRS without explicit AXIS order, but that the same " 
 1553                                            "SRS authority code imported with ImportFromEPSGA() should be " 
 1554                                            "treated as lat/long, then the function will take care of coordinate " 
 1555                                            "order swapping. If set to NO, SRS with EPSG authority will be " 
 1556                                            "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
 
 1561                               QObject::tr( 
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. " 
 1562                                            "If set to NO, the <gml:boundedBy> element will not be written for " 
 1568                               QObject::tr( 
"Default to YES. If YES, the output will be indented with spaces " 
 1569                                            "for more readability, but at the expense of file size." ),
 
 1574      driverMetadata.insert( QStringLiteral( 
"GML" ),
 
 1576                               QStringLiteral( 
"Geography Markup Language [GML]" ),
 
 1577                               QObject::tr( 
"Geography Markup Language [GML]" ),
 
 1578                               QStringLiteral( 
"*.gml" ),
 
 1579                               QStringLiteral( 
"gml" ),
 
 1582                               QStringLiteral( 
"UTF-8" )
 
 1587      datasetOptions.clear();
 
 1588      layerOptions.clear();
 
 1591                             QObject::tr( 
"Human-readable identifier (e.g. short name) for the layer content" ),
 
 1596                             QObject::tr( 
"Human-readable description for the layer content" ),
 
 1601                             QObject::tr( 
"Name for the feature identifier column" ),
 
 1602                             QStringLiteral( 
"fid" )  
 
 1606                             QObject::tr( 
"Name for the geometry column" ),
 
 1607                             QStringLiteral( 
"geom" )  
 
 1611                             QObject::tr( 
"If a spatial index must be created." ),
 
 1615      driverMetadata.insert( QStringLiteral( 
"GPKG" ),
 
 1617                               QStringLiteral( 
"GeoPackage" ),
 
 1618                               QObject::tr( 
"GeoPackage" ),
 
 1619#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
 
 1620                               QStringLiteral( 
"*.gpkg *.gpkg.zip" ),
 
 1622                               QStringLiteral( 
"*.gpkg" ),
 
 1624                               QStringLiteral( 
"gpkg" ),
 
 1627                               QStringLiteral( 
"UTF-8" )
 
 1632      datasetOptions.clear();
 
 1633      layerOptions.clear();
 
 1635      driverMetadata.insert( QStringLiteral( 
"GMT" ),
 
 1637                               QStringLiteral( 
"Generic Mapping Tools [GMT]" ),
 
 1638                               QObject::tr( 
"Generic Mapping Tools [GMT]" ),
 
 1639                               QStringLiteral( 
"*.gmt" ),
 
 1640                               QStringLiteral( 
"gmt" ),
 
 1647      datasetOptions.clear();
 
 1648      layerOptions.clear();
 
 1651                             QObject::tr( 
"By default when writing a layer whose features are of " 
 1652                                          "type wkbLineString, the GPX driver chooses to write " 
 1653                                          "them as routes. If FORCE_GPX_TRACK=YES is specified, " 
 1654                                          "they will be written as tracks." ),
 
 1659                             QObject::tr( 
"By default when writing a layer whose features are of " 
 1660                                          "type wkbMultiLineString, the GPX driver chooses to write " 
 1661                                          "them as tracks. If FORCE_GPX_ROUTE=YES is specified, " 
 1662                                          "they will be written as routes, provided that the multilines " 
 1663                                          "are composed of only one single line." ),
 
 1668                               QObject::tr( 
"If GPX_USE_EXTENSIONS=YES is specified, " 
 1669                                            "extra fields will be written inside the <extensions> tag." ),
 
 1674                               QObject::tr( 
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL " 
 1675                                            "is set. The namespace value used for extension tags. By default, 'ogr'." ),
 
 1676                               QStringLiteral( 
"ogr" )  
 
 1680                               QObject::tr( 
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS " 
 1681                                            "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
 
 1682                               QStringLiteral( 
"http://osgeo.org/gdal" )  
 
 1686                               QObject::tr( 
"By default files are created with the line termination " 
 1687                                            "conventions of the local platform (CR/LF on win32 or LF " 
 1688                                            "on all other systems). This may be overridden through use " 
 1689                                            "of the LINEFORMAT layer creation option which may have a value " 
 1690                                            "of CRLF (DOS format) or LF (Unix format)." ),
 
 1692                               << QStringLiteral( 
"CRLF" )
 
 1693                               << QStringLiteral( 
"LF" ),
 
 1698      driverMetadata.insert( QStringLiteral( 
"GPX" ),
 
 1700                               QStringLiteral( 
"GPS eXchange Format [GPX]" ),
 
 1701                               QObject::tr( 
"GPS eXchange Format [GPX]" ),
 
 1702                               QStringLiteral( 
"*.gpx" ),
 
 1703                               QStringLiteral( 
"gpx" ),
 
 1706                               QStringLiteral( 
"UTF-8" )
 
 1711      datasetOptions.clear();
 
 1712      layerOptions.clear();
 
 1714      driverMetadata.insert( QStringLiteral( 
"Interlis 1" ),
 
 1716                               QStringLiteral( 
"INTERLIS 1" ),
 
 1717                               QObject::tr( 
"INTERLIS 1" ),
 
 1718                               QStringLiteral( 
"*.itf *.xml *.ili" ),
 
 1719                               QStringLiteral( 
"ili" ),
 
 1726      datasetOptions.clear();
 
 1727      layerOptions.clear();
 
 1729      driverMetadata.insert( QStringLiteral( 
"Interlis 2" ),
 
 1731                               QStringLiteral( 
"INTERLIS 2" ),
 
 1732                               QObject::tr( 
"INTERLIS 2" ),
 
 1733                               QStringLiteral( 
"*.xtf *.xml *.ili" ),
 
 1734                               QStringLiteral( 
"ili" ),
 
 1741      datasetOptions.clear();
 
 1742      layerOptions.clear();
 
 1745                               QObject::tr( 
"Allows you to specify the field to use for the KML <name> element." ),
 
 1746                               QStringLiteral( 
"Name" )  
 
 1750                               QObject::tr( 
"Allows you to specify the field to use for the KML <description> element." ),
 
 1751                               QStringLiteral( 
"Description" )  
 
 1755                               QObject::tr( 
"Allows you to specify the AltitudeMode to use for KML geometries. " 
 1756                                            "This will only affect 3D geometries and must be one of the valid KML options." ),
 
 1758                               << QStringLiteral( 
"clampToGround" )
 
 1759                               << QStringLiteral( 
"relativeToGround" )
 
 1760                               << QStringLiteral( 
"absolute" ),
 
 1761                               QStringLiteral( 
"relativeToGround" ) 
 
 1765                               QObject::tr( 
"The DOCUMENT_ID datasource creation option can be used to specified " 
 1766                                            "the id of the root <Document> node. The default value is root_doc." ),
 
 1767                               QStringLiteral( 
"root_doc" )  
 
 1770      driverMetadata.insert( QStringLiteral( 
"KML" ),
 
 1772                               QStringLiteral( 
"Keyhole Markup Language [KML]" ),
 
 1773                               QObject::tr( 
"Keyhole Markup Language [KML]" ),
 
 1774                               QStringLiteral( 
"*.kml" ),
 
 1775                               QStringLiteral( 
"kml" ),
 
 1778                               QStringLiteral( 
"UTF-8" )
 
 1783      datasetOptions.clear();
 
 1784      layerOptions.clear();
 
 1786      auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
 
 1789                                 QObject::tr( 
"Use this to turn on 'quick spatial index mode'. " 
 1790                                              "In this mode writing files can be about 5 times faster, " 
 1791                                              "but spatial queries can be up to 30 times slower." ),
 
 1793                                 << QStringLiteral( 
"QUICK" )
 
 1794                                 << QStringLiteral( 
"OPTIMIZED" ),
 
 1795                                 QStringLiteral( 
"QUICK" ), 
 
 1800                                 QObject::tr( 
"(multiples of 512): Block size for .map files. Defaults " 
 1801                                              "to 512. MapInfo 15.2 and above creates .tab files with a " 
 1802                                              "blocksize of 16384 bytes. Any MapInfo version should be " 
 1803                                              "able to handle block sizes from 512 to 32256." ),
 
 1807                               QObject::tr( 
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the " 
 1808                                            "accuracy of the coordinates. Note: the geometry of written " 
 1809                                            "features must be within the defined box." ),
 
 1813      insertMapInfoOptions( datasetOptions, layerOptions );
 
 1815      driverMetadata.insert( QStringLiteral( 
"MapInfo File" ),
 
 1817                               QStringLiteral( 
"Mapinfo" ),
 
 1818                               QObject::tr( 
"Mapinfo TAB" ),
 
 1819                               QStringLiteral( 
"*.tab" ),
 
 1820                               QStringLiteral( 
"tab" ),
 
 1825      datasetOptions.clear();
 
 1826      layerOptions.clear();
 
 1827      insertMapInfoOptions( datasetOptions, layerOptions );
 
 1830      driverMetadata.insert( QStringLiteral( 
"MapInfo MIF" ),
 
 1832                               QStringLiteral( 
"Mapinfo" ),
 
 1833                               QObject::tr( 
"Mapinfo MIF" ),
 
 1834                               QStringLiteral( 
"*.mif" ),
 
 1835                               QStringLiteral( 
"mif" ),
 
 1842      datasetOptions.clear();
 
 1843      layerOptions.clear();
 
 1846                               QObject::tr( 
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) " 
 1847                                            "seed file should be used. This option is ignored if the SEED option is provided." ),
 
 1852                               QObject::tr( 
"Override the seed file to use." ),
 
 1857                               QObject::tr( 
"Indicate whether the whole seed file should be copied. " 
 1858                                            "If not, only the first three elements will be copied." ),
 
 1863                               QObject::tr( 
"Indicates whether the color table should be copied from the seed file." ),
 
 1868                               QObject::tr( 
"Override the master unit name from the seed file with " 
 1869                                            "the provided one or two character unit name." ),
 
 1874                               QObject::tr( 
"Override the sub unit name from the seed file with the provided " 
 1875                                            "one or two character unit name." ),
 
 1880                               QObject::tr( 
"Override the number of subunits per master unit. " 
 1881                                            "By default the seed file value is used." ),
 
 1886                               QObject::tr( 
"Override the number of UORs (Units of Resolution) " 
 1887                                            "per sub unit. By default the seed file value is used." ),
 
 1892                               QObject::tr( 
"ORIGIN=x,y,z: Override the origin of the design plane. " 
 1893                                            "By default the origin from the seed file is used." ),
 
 1897      driverMetadata.insert( QStringLiteral( 
"DGN" ),
 
 1899                               QStringLiteral( 
"Microstation DGN" ),
 
 1900                               QObject::tr( 
"Microstation DGN" ),
 
 1901                               QStringLiteral( 
"*.dgn" ),
 
 1902                               QStringLiteral( 
"dgn" ),
 
 1909      datasetOptions.clear();
 
 1910      layerOptions.clear();
 
 1913                               QObject::tr( 
"Should update files be incorporated into the base data on the fly." ),
 
 1915                               << QStringLiteral( 
"APPLY" )
 
 1916                               << QStringLiteral( 
"IGNORE" ),
 
 1917                               QStringLiteral( 
"APPLY" ) 
 
 1921                               QObject::tr( 
"Should multipoint soundings be split into many single point sounding features. " 
 1922                                            "Multipoint geometries are not well handled by many formats, " 
 1923                                            "so it can be convenient to split single sounding features with many points " 
 1924                                            "into many single point features." ),
 
 1929                               QObject::tr( 
"Should a DEPTH attribute be added on SOUNDG features and assign the depth " 
 1930                                            "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is " 
 1936                               QObject::tr( 
"Should all the low level geometry primitives be returned as special " 
 1937                                            "IsolatedNode, ConnectedNode, Edge and Face layers." ),
 
 1942                               QObject::tr( 
"If enabled, numeric attributes assigned an empty string as a value will " 
 1943                                            "be preserved as a special numeric value. This option should not generally " 
 1944                                            "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
 
 1949                               QObject::tr( 
"Should LNAM and LNAM_REFS fields be attached to features capturing " 
 1950                                            "the feature to feature relationships in the FFPT group of the S-57 file." ),
 
 1955                               QObject::tr( 
"Should additional attributes relating features to their underlying " 
 1956                                            "geometric primitives be attached. These are the values of the FSPT group, " 
 1957                                            "and are primarily needed when doing S-57 to S-57 translations." ),
 
 1962                               QObject::tr( 
"Should attribute values be recoded to UTF-8 from the character encoding " 
 1963                                            "specified in the S57 DSSI record." ),
 
 1969      driverMetadata.insert( QStringLiteral( 
"S57" ),
 
 1971                               QStringLiteral( 
"S-57 Base file" ),
 
 1972                               QObject::tr( 
"S-57 Base file" ),
 
 1973                               QStringLiteral( 
"*.000" ),
 
 1974                               QStringLiteral( 
"000" ),
 
 1981      datasetOptions.clear();
 
 1982      layerOptions.clear();
 
 1984      driverMetadata.insert( QStringLiteral( 
"SDTS" ),
 
 1986                               QStringLiteral( 
"Spatial Data Transfer Standard [SDTS]" ),
 
 1987                               QObject::tr( 
"Spatial Data Transfer Standard [SDTS]" ),
 
 1988                               QStringLiteral( 
"*catd.ddf" ),
 
 1989                               QStringLiteral( 
"ddf" ),
 
 1996      datasetOptions.clear();
 
 1997      layerOptions.clear();
 
 2000                               QObject::tr( 
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 
 2001                                            "tables in a new database. By default these metadata tables are created " 
 2002                                            "when a new database is created." ),
 
 2008                               QStringLiteral( 
"NO" )
 
 2013                               QStringLiteral( 
"NO" )
 
 2017                             QObject::tr( 
"Controls the format used for the geometry column. Defaults to WKB. " 
 2018                                          "This is generally more space and processing efficient, but harder " 
 2019                                          "to inspect or use in simple applications than WKT (Well Known Text)." ),
 
 2021                             << QStringLiteral( 
"WKB" )
 
 2022                             << QStringLiteral( 
"WKT" ),
 
 2023                             QStringLiteral( 
"WKB" ) 
 
 2027                             QObject::tr( 
"Controls whether layer and field names will be laundered for easier use " 
 2028                                          "in SQLite. Laundered names will be converted to lower case and some special " 
 2029                                          "characters(' - #) will be changed to underscores." ),
 
 2034                             QStringLiteral( 
"NO" )
 
 2038                             QStringLiteral( 
"NO" )
 
 2046                             QObject::tr( 
"column_name1[,column_name2, …] A list of (String) columns that " 
 2047                                          "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 
 2048                                          "for databases that have big string blobs. However, use with care, since " 
 2049                                          "the value of such columns will be seen as compressed binary content with " 
 2050                                          "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 
 2051                                          "modifying or querying compressed columns, compression/decompression is " 
 2052                                          "done transparently. However, such columns cannot be (easily) queried with " 
 2053                                          "an attribute filter or WHERE clause. Note: in table definition, such columns " 
 2054                                          "have the 'VARCHAR_deflate' declaration type." ),
 
 2058      driverMetadata.insert( QStringLiteral( 
"SQLite" ),
 
 2060                               QStringLiteral( 
"SQLite" ),
 
 2061                               QObject::tr( 
"SQLite" ),
 
 2062                               QStringLiteral( 
"*.sqlite" ),
 
 2063                               QStringLiteral( 
"sqlite" ),
 
 2066                               QStringLiteral( 
"UTF-8" )
 
 2071      datasetOptions.clear();
 
 2072      layerOptions.clear();
 
 2075                               QObject::tr( 
"Can be used to avoid creating the geometry_columns and spatial_ref_sys " 
 2076                                            "tables in a new database. By default these metadata tables are created " 
 2077                                            "when a new database is created." ),
 
 2082                               QStringLiteral( 
"YES" )
 
 2086                               QObject::tr( 
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. " 
 2087                                            "Set to NO for regular SQLite databases." ),
 
 2092                             QStringLiteral( 
"SPATIALITE" )
 
 2096                             QObject::tr( 
"Controls whether layer and field names will be laundered for easier use " 
 2097                                          "in SQLite. Laundered names will be converted to lower case and some special " 
 2098                                          "characters(' - #) will be changed to underscores." ),
 
 2103                             QObject::tr( 
"If the database is of the SpatiaLite flavor, and if OGR is linked " 
 2104                                          "against libspatialite, this option can be used to control if a spatial " 
 2105                                          "index must be created." ),
 
 2110                             QObject::tr( 
"If the format of the geometry BLOB is of the SpatiaLite flavor, " 
 2111                                          "this option can be used to control if the compressed format for " 
 2112                                          "geometries (LINESTRINGs, POLYGONs) must be used." ),
 
 2117                             QObject::tr( 
"Used to force the SRID number of the SRS associated with the layer. " 
 2118                                          "When this option isn't specified and that a SRS is associated with the " 
 2119                                          "layer, a search is made in the spatial_ref_sys to find a match for the " 
 2120                                          "SRS, and, if there is no match, a new entry is inserted for the SRS in " 
 2121                                          "the spatial_ref_sys table. When the SRID option is specified, this " 
 2122                                          "search (and the eventual insertion of a new entry) will not be done: " 
 2123                                          "the specified SRID is used as such." ),
 
 2128                             QObject::tr( 
"column_name1[,column_name2, …] A list of (String) columns that " 
 2129                                          "must be compressed with ZLib DEFLATE algorithm. This might be beneficial " 
 2130                                          "for databases that have big string blobs. However, use with care, since " 
 2131                                          "the value of such columns will be seen as compressed binary content with " 
 2132                                          "other SQLite utilities (or previous OGR versions). With OGR, when inserting, " 
 2133                                          "modifying or queryings compressed columns, compression/decompression is " 
 2134                                          "done transparently. However, such columns cannot be (easily) queried with " 
 2135                                          "an attribute filter or WHERE clause. Note: in table definition, such columns " 
 2136                                          "have the 'VARCHAR_deflate' declaration type." ),
 
 2140      driverMetadata.insert( QStringLiteral( 
"SpatiaLite" ),
 
 2142                               QStringLiteral( 
"SpatiaLite" ),
 
 2143                               QObject::tr( 
"SpatiaLite" ),
 
 2144                               QStringLiteral( 
"*.sqlite" ),
 
 2145                               QStringLiteral( 
"sqlite" ),
 
 2148                               QStringLiteral( 
"UTF-8" )
 
 2152      datasetOptions.clear();
 
 2153      layerOptions.clear();
 
 2156                               QObject::tr( 
"Override the header file used - in place of header.dxf." ),
 
 2161                               QObject::tr( 
"Override the trailer file used - in place of trailer.dxf." ),
 
 2165      driverMetadata.insert( QStringLiteral( 
"DXF" ),
 
 2167                               QStringLiteral( 
"AutoCAD DXF" ),
 
 2168                               QObject::tr( 
"AutoCAD DXF" ),
 
 2169                               QStringLiteral( 
"*.dxf" ),
 
 2170                               QStringLiteral( 
"dxf" ),
 
 2177      datasetOptions.clear();
 
 2178      layerOptions.clear();
 
 2181                               QObject::tr( 
"Indicates the GeoConcept export file extension. " 
 2182                                            "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
 
 2184                               << QStringLiteral( 
"GXT" )
 
 2185                               << QStringLiteral( 
"TXT" ),
 
 2186                               QStringLiteral( 
"GXT" ) 
 
 2190                               QObject::tr( 
"Path to the GCT: the GCT file describes the GeoConcept types definitions: " 
 2191                                            "In this file, every line must start with //# followed by a keyword. " 
 2192                                            "Lines starting with // are comments." ),
 
 2197                               QObject::tr( 
"Defines the feature to be created. The TYPE corresponds to one of the Name " 
 2198                                            "found in the GCT file for a type section. The SUBTYPE corresponds to one of " 
 2199                                            "the Name found in the GCT file for a sub-type section within the previous " 
 2204      driverMetadata.insert( QStringLiteral( 
"Geoconcept" ),
 
 2206                               QStringLiteral( 
"Geoconcept" ),
 
 2207                               QObject::tr( 
"Geoconcept" ),
 
 2208                               QStringLiteral( 
"*.gxt *.txt" ),
 
 2209                               QStringLiteral( 
"gxt" ),
 
 2216      datasetOptions.clear();
 
 2217      layerOptions.clear();
 
 2219#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0) 
 2221                             QObject::tr( 
"Selects which ArcGIS version this dataset should be compatible with. ALL is used by default and means any ArcGIS 10.x or ArcGIS Pro version. Using ARCGIS_PRO_3_2_OR_LATER is required to export 64-bit integer fields as such, otherwise they will be converted as Real fields. ARCGIS_PRO_3_2_OR_LATER also supports proper Date and Time field types." ),
 
 2223                             << QStringLiteral( 
"ALL" )
 
 2224                             << QStringLiteral( 
"ARCGIS_PRO_3_2_OR_LATER" ),
 
 2225                             QStringLiteral( 
"ALL" ) 
 
 2230                             QObject::tr( 
"When this option is set, the new layer will be created inside the named " 
 2231                                          "FeatureDataset folder. If the folder does not already exist, it will be created." ),
 
 2236                             QObject::tr( 
"Set layer name alias." ),
 
 2241                             QObject::tr( 
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
 
 2242                             QStringLiteral( 
"SHAPE" )  
 
 2246                             QObject::tr( 
"Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to 'YES'." ),
 
 2251                             QObject::tr( 
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
 
 2252                             QStringLiteral( 
"OBJECTID" )  
 
 2268                             QObject::tr( 
"A list of strings of format field_name=fgdb_field_type (separated by comma) to force the FileGDB column type of fields to be created." ),
 
 2273                             QObject::tr( 
"XML documentation for the layer." ),
 
 2277                             QObject::tr( 
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
 
 2278      {QStringLiteral( 
"DEFAULTS" ), QStringLiteral( 
"MAX_FILE_SIZE_4GB" ), QStringLiteral( 
"MAX_FILE_SIZE_256TB" )},
 
 2279      QStringLiteral( 
"DEFAULTS" ), 
 
 2284                             QObject::tr( 
" Defaults to NO (through CreateLayer() API). When this option is set, a Shape_Area and Shape_Length special fields will be created for polygonal layers (Shape_Length only for linear layers). These fields will automatically be populated with the feature’s area or length whenever a new feature is added to the dataset or an existing feature is amended. When using ogr2ogr with a source layer that has Shape_Area/Shape_Length special fields, and this option is not explicitly specified, it will be automatically set, so that the resulting FileGeodatabase has those fields properly tagged." ),
 
 2288      driverMetadata.insert( QStringLiteral( 
"OpenFileGDB" ),
 
 2290                               QStringLiteral( 
"ESRI File Geodatabase" ),
 
 2291                               QObject::tr( 
"ESRI File Geodatabase" ),
 
 2292                               QStringLiteral( 
"*.gdb" ),
 
 2293                               QStringLiteral( 
"gdb" ),
 
 2296                               QStringLiteral( 
"UTF-8" )
 
 2300#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,11,0) 
 2302      datasetOptions.clear();
 
 2303      layerOptions.clear();
 
 2306                             QObject::tr( 
"When this option is set, the new layer will be created inside the named " 
 2307                                          "FeatureDataset folder. If the folder does not already exist, it will be created." ),
 
 2312                             QObject::tr( 
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
 
 2313                             QStringLiteral( 
"SHAPE" )  
 
 2317                             QObject::tr( 
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
 
 2318                             QStringLiteral( 
"OBJECTID" )  
 
 2321      driverMetadata.insert( QStringLiteral( 
"FileGDB" ),
 
 2323                               QStringLiteral( 
"ESRI FileGDB" ),
 
 2324                               QObject::tr( 
"ESRI FileGDB" ),
 
 2325                               QStringLiteral( 
"*.gdb" ),
 
 2326                               QStringLiteral( 
"gdb" ),
 
 2329                               QStringLiteral( 
"UTF-8" )
 
 2335      datasetOptions.clear();
 
 2336      layerOptions.clear();
 
 2339                             QObject::tr( 
"By default, the driver will try to detect the data type of fields. If set " 
 2340                                          "to STRING, all fields will be of String type." ),
 
 2342                             << QStringLiteral( 
"AUTO" )
 
 2343                             << QStringLiteral( 
"STRING" ),
 
 2344                             QStringLiteral( 
"AUTO" ), 
 
 2349                             QObject::tr( 
"By default, the driver will read the first lines of each sheet to detect " 
 2350                                          "if the first line might be the name of columns. If set to FORCE, the driver " 
 2351                                          "will consider the first line as the header line. If set to " 
 2352                                          "DISABLE, it will be considered as the first feature. Otherwise " 
 2353                                          "auto-detection will occur." ),
 
 2355                             << QStringLiteral( 
"FORCE" )
 
 2356                             << QStringLiteral( 
"DISABLE" )
 
 2357                             << QStringLiteral( 
"AUTO" ),
 
 2358                             QStringLiteral( 
"AUTO" ), 
 
 2362      driverMetadata.insert( QStringLiteral( 
"XLSX" ),
 
 2364                               QStringLiteral( 
"MS Office Open XML spreadsheet" ),
 
 2365                               QObject::tr( 
"MS Office Open XML spreadsheet [XLSX]" ),
 
 2366                               QStringLiteral( 
"*.xlsx" ),
 
 2367                               QStringLiteral( 
"xlsx" ),
 
 2370                               QStringLiteral( 
"UTF-8" )
 
 2375      datasetOptions.clear();
 
 2376      layerOptions.clear();
 
 2379                             QObject::tr( 
"By default, the driver will try to detect the data type of fields. If set " 
 2380                                          "to STRING, all fields will be of String type." ),
 
 2382                             << QStringLiteral( 
"AUTO" )
 
 2383                             << QStringLiteral( 
"STRING" ),
 
 2384                             QStringLiteral( 
"AUTO" ), 
 
 2389                             QObject::tr( 
"By default, the driver will read the first lines of each sheet to detect " 
 2390                                          "if the first line might be the name of columns. If set to FORCE, the driver " 
 2391                                          "will consider the first line as the header line. If set to " 
 2392                                          "DISABLE, it will be considered as the first feature. Otherwise " 
 2393                                          "auto-detection will occur." ),
 
 2395                             << QStringLiteral( 
"FORCE" )
 
 2396                             << QStringLiteral( 
"DISABLE" )
 
 2397                             << QStringLiteral( 
"AUTO" ),
 
 2398                             QStringLiteral( 
"AUTO" ), 
 
 2402      driverMetadata.insert( QStringLiteral( 
"ODS" ),
 
 2404                               QStringLiteral( 
"Open Document Spreadsheet" ),
 
 2405                               QObject::tr( 
"Open Document Spreadsheet [ODS]" ),
 
 2406                               QStringLiteral( 
"*.ods" ),
 
 2407                               QStringLiteral( 
"ods" ),
 
 2410                               QStringLiteral( 
"UTF-8" )
 
 2415      datasetOptions.clear();
 
 2416      layerOptions.clear();
 
 2419                             QObject::tr( 
"Compression method." ),
 
 2421                             << QStringLiteral( 
"UNCOMPRESSED" )
 
 2422                             << QStringLiteral( 
"SNAPPY" ),
 
 2423                             QStringLiteral( 
"SNAPPY" ), 
 
 2428                             QObject::tr( 
"Geometry encoding." ),
 
 2430                             << QStringLiteral( 
"WKB" )
 
 2431                             << QStringLiteral( 
"WKT" )
 
 2432                             << QStringLiteral( 
"GEOARROW" ),
 
 2433                             QStringLiteral( 
"WKB" ), 
 
 2438                             QObject::tr( 
"Maximum number of rows per group." ),
 
 2443                             QObject::tr( 
"Name for the feature identifier column" ),
 
 2448                             QObject::tr( 
"Name for the geometry column" ),
 
 2449                             QStringLiteral( 
"geometry" )  
 
 2453                             QObject::tr( 
"Name of the coordinate system for the edges." ),
 
 2455                             << QStringLiteral( 
"PLANAR" )
 
 2456                             << QStringLiteral( 
"SPHERICAL" ),
 
 2457                             QStringLiteral( 
"PLANAR" ), 
 
 2461      driverMetadata.insert( QStringLiteral( 
"Parquet" ),
 
 2463                               QStringLiteral( 
"(Geo)Parquet" ),
 
 2464                               QObject::tr( 
"(Geo)Parquet" ),
 
 2465                               QStringLiteral( 
"*.parquet" ),
 
 2466                               QStringLiteral( 
"parquet" ),
 
 2469                               QStringLiteral( 
"UTF-8" )
 
 2474      datasetOptions.clear();
 
 2475      layerOptions.clear();
 
 2478                               QObject::tr( 
"Line termination character sequence." ),
 
 2480                               << QStringLiteral( 
"CRLF" )
 
 2481                               << QStringLiteral( 
"LF" ),
 
 2482                               QStringLiteral( 
"LF" ), 
 
 2488                             QObject::tr( 
"Format of geometry columns." ),
 
 2490                             << QStringLiteral( 
"geometry" )
 
 2491                             << QStringLiteral( 
"geography" ),
 
 2492                             QStringLiteral( 
"geometry" ), 
 
 2497                             QObject::tr( 
"Controls whether layer and field names will be laundered for easier use. " 
 2498                                          "Laundered names will be converted to lower case and some special " 
 2499                                          "characters(' - #) will be changed to underscores." ),
 
 2504                             QObject::tr( 
"Name for the geometry column. Defaults to wkb_geometry " 
 2505                                          "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
 
 2508                             QObject::tr( 
"Name of schema into which to create the new table" ) ) );
 
 2511                             QObject::tr( 
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
 
 2516                             QObject::tr( 
"Whether to explicitly recreate the table if necessary." ),
 
 2521                             QObject::tr( 
"Whether to explicitly destroy tables before recreating them." ),
 
 2523                             << QStringLiteral( 
"YES" )
 
 2524                             << QStringLiteral( 
"NO" )
 
 2525                             << QStringLiteral( 
"IF_EXISTS" ),
 
 2526                             QStringLiteral( 
"YES" ), 
 
 2531                             QObject::tr( 
"Used to force the SRID number of the SRS associated with the layer. " 
 2532                                          "When this option isn't specified and that a SRS is associated with the " 
 2533                                          "layer, a search is made in the spatial_ref_sys to find a match for the " 
 2534                                          "SRS, and, if there is no match, a new entry is inserted for the SRS in " 
 2535                                          "the spatial_ref_sys table. When the SRID option is specified, this " 
 2536                                          "search (and the eventual insertion of a new entry) will not be done: " 
 2537                                          "the specified SRID is used as such." ),
 
 2542                             QObject::tr( 
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. " 
 2543                                          "Important to set it correctly if using non-linear geometry types" ),
 
 2544                             QStringLiteral( 
"2.2" ) 
 
 2547      driverMetadata.insert( QStringLiteral( 
"PGDUMP" ),
 
 2549                               QStringLiteral( 
"PostgreSQL SQL dump" ),
 
 2550                               QObject::tr( 
"PostgreSQL SQL dump" ),
 
 2551                               QStringLiteral( 
"*.sql" ),
 
 2552                               QStringLiteral( 
"sql" ),
 
 2555                               QStringLiteral( 
"UTF-8" )
 
 2561    QgsVectorFileWriterMetadataContainer( 
const QgsVectorFileWriterMetadataContainer &other ) = 
delete;
 
 2562    QgsVectorFileWriterMetadataContainer &operator=( 
const QgsVectorFileWriterMetadataContainer &other ) = 
delete;
 
 2563    ~QgsVectorFileWriterMetadataContainer()
 
 2565      for ( 
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
 
 2567        for ( 
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
 
 2568          delete optionIt.value();
 
 2569        for ( 
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
 
 2570          delete optionIt.value();
 
 2574    QMap<QString,  QgsVectorFileWriter::MetaData> driverMetadata;
 
 2581  static QgsVectorFileWriterMetadataContainer sDriverMetadata;
 
 2582  QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
 
 2584  for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
 
 2586    if ( it.key() == QLatin1String( 
"PGDUMP" ) &&
 
 2587         driverName != QLatin1String( 
"PGDUMP" ) &&
 
 2588         driverName != QLatin1String( 
"PostgreSQL SQL dump" ) )
 
 2593    if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
 
 
 2608    return QStringList();
 
 
 2617    return QStringList();
 
 
 2624  OGRwkbGeometryType ogrType = 
static_cast<OGRwkbGeometryType
>( type );
 
 
 2655  return mCapabilities;
 
 
 2665  QgsFeatureList::iterator fIt = features.begin();
 
 2667  for ( ; fIt != features.end(); ++fIt )
 
 
 2692    QString styleString;
 
 2693    QString currentStyle;
 
 2695    QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
 
 2696    for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
 
 2698      int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
 
 2699      for ( 
int i = 0; i < nSymbolLayers; ++i )
 
 2702        QMap< QgsSymbolLayer *, QString >::const_iterator it = 
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
 
 2708        double mmsf = mmScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
 
 2709        double musf = mapUnitScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
 
 2711        currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
 
 2717            if ( symbolIt != symbols.constBegin() || i != 0 )
 
 2719              styleString.append( 
';' );
 
 2721            styleString.append( currentStyle );
 
 2726            OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
 
 2727            if ( !writeFeature( 
mLayer, poFeature.get() ) )
 
 2739    OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
 
 2747      if ( !writeFeature( 
mLayer, poFeature.get() ) )
 
 
 2771    int fldIdx = it.key();
 
 2772    int ogrField = it.value();
 
 2774    QVariant attrValue = feature.
attribute( fldIdx );
 
 2779      OGR_F_UnsetField( poFeature.get(), ogrField );
 
 2792      OGR_F_SetFieldNull( poFeature.get(), ogrField );
 
 2807      mErrorMessage = QObject::tr( 
"Error converting value (%1) for attribute field %2: %3" )
 
 2808                      .arg( feature.
attribute( fldIdx ).toString(),
 
 2815    switch ( field.
type() )
 
 2817      case QMetaType::Type::Int:
 
 2818        OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
 
 2820      case QMetaType::Type::LongLong:
 
 2821        OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
 
 2823      case QMetaType::Type::Bool:
 
 2824        OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
 
 2826      case QMetaType::Type::QString:
 
 2827        OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toString() ).constData() );
 
 2829      case QMetaType::Type::Double:
 
 2830        OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
 
 2832      case QMetaType::Type::QDate:
 
 2833        OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
 
 2834                                attrValue.toDate().year(),
 
 2835                                attrValue.toDate().month(),
 
 2836                                attrValue.toDate().day(),
 
 2839      case QMetaType::Type::QDateTime:
 
 2842          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral( 
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
 
 2846          const QDateTime dt = attrValue.toDateTime();
 
 2847          const QDate date = dt.date();
 
 2848          const QTime time = dt.time();
 
 2849          OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
 
 2855                                    static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 ),
 
 2859      case QMetaType::Type::QTime:
 
 2862          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( attrValue.toString() ).constData() );
 
 2866          const QTime time = attrValue.toTime();
 
 2867          OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
 
 2871                                    static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 ),
 
 2876      case QMetaType::Type::QByteArray:
 
 2878        const QByteArray ba = attrValue.toByteArray();
 
 2879        OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(), 
const_cast< GByte * 
>( 
reinterpret_cast< const GByte * 
>( ba.data() ) ) );
 
 2883      case QMetaType::Type::UnknownType:
 
 2886      case QMetaType::Type::QStringList:
 
 2891          const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
 
 2893          if ( !doc.isNull() )
 
 2895            jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
 
 2897          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( jsonString.constData() ) );
 
 2901        QStringList list = attrValue.toStringList();
 
 2902        if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
 
 2904          int count = list.count();
 
 2905          char **lst = 
new char *[count + 1];
 
 2909            for ( 
const QString &
string : list )
 
 2911              lst[pos] = CPLStrdup( 
mCodec->fromUnicode( 
string ).data() );
 
 2915          lst[count] = 
nullptr;
 
 2916          OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
 
 2921          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( list.join( 
',' ) ).constData() );
 
 2926      case QMetaType::Type::QVariantList:
 
 2930          const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
 
 2932          if ( !doc.isNull() )
 
 2934            jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
 
 2936          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( jsonString.constData() ) );
 
 2941        if ( field.
subType() == QMetaType::Type::QString )
 
 2943          QStringList list = attrValue.toStringList();
 
 2944          if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
 
 2946            int count = list.count();
 
 2947            char **lst = 
new char *[count + 1];
 
 2951              for ( 
const QString &
string : list )
 
 2953                lst[pos] = CPLStrdup( 
mCodec->fromUnicode( 
string ).data() );
 
 2957            lst[count] = 
nullptr;
 
 2958            OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
 
 2963            OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( list.join( 
',' ) ).constData() );
 
 2967        else if ( field.
subType() == QMetaType::Type::Int )
 
 2969          const QVariantList list = attrValue.toList();
 
 2970          if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
 
 2972            const int count = list.count();
 
 2973            int *lst = 
new int[count];
 
 2977              for ( 
const QVariant &value : list )
 
 2979                lst[pos] = value.toInt();
 
 2983            OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
 
 2988            QStringList strings;
 
 2989            strings.reserve( list.size() );
 
 2990            for ( 
const QVariant &value : list )
 
 2992              strings << QString::number( value.toInt() );
 
 2994            OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 2998        else if ( field.
subType() == QMetaType::Type::Double )
 
 3000          const QVariantList list = attrValue.toList();
 
 3001          if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
 
 3003            const int count = list.count();
 
 3004            double *lst = 
new double[count];
 
 3008              for ( 
const QVariant &value : list )
 
 3010                lst[pos] = value.toDouble();
 
 3014            OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
 
 3019            QStringList strings;
 
 3020            strings.reserve( list.size() );
 
 3021            for ( 
const QVariant &value : list )
 
 3023              strings << QString::number( value.toDouble() );
 
 3025            OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 3029        else if ( field.
subType() == QMetaType::Type::LongLong )
 
 3031          const QVariantList list = attrValue.toList();
 
 3032          if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
 
 3034            const int count = list.count();
 
 3035            long long *lst = 
new long long[count];
 
 3039              for ( 
const QVariant &value : list )
 
 3041                lst[pos] = value.toLongLong();
 
 3045            OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
 
 3050            QStringList strings;
 
 3051            strings.reserve( list.size() );
 
 3052            for ( 
const QVariant &value : list )
 
 3054              strings << QString::number( value.toLongLong() );
 
 3056            OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( strings.join( 
',' ) ).constData() );
 
 3063      case QMetaType::Type::QVariantMap:
 
 3066        const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName( 
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES, 
nullptr );
 
 3067        if ( pszDataSubTypes && strstr( pszDataSubTypes, 
"JSON" ) )
 
 3069          const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
 
 3071          if ( !doc.isNull() )
 
 3073            const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
 
 3074            jsonString = QString::fromUtf8( json.data() );
 
 3076          OGR_F_SetFieldString( poFeature.get(), ogrField, 
mCodec->fromUnicode( jsonString.constData() ) );
 
 3086        mErrorMessage = QObject::tr( 
"Invalid variant type for field %1[%2]: received %3 with type %4" )
 
 3089                        .arg( attrValue.typeName(),
 
 3090                              attrValue.toString() );
 
 3103      if ( mCoordinateTransform )
 
 3108          geom.
transform( *mCoordinateTransform );
 
 3126        OGRGeometryH mGeom2 = 
nullptr;
 
 3155            geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
 
 3162            geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
 
 3182          mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 3183                          .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 3193        QByteArray wkb( geom.
asWkb( wkbFlags ) );
 
 3194        OGRErr err = OGR_G_ImportFromWkb( mGeom2, 
reinterpret_cast<unsigned char *
>( 
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
 
 3195        if ( err != OGRERR_NONE )
 
 3197          mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 3198                          .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 3205        OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
 
 3213        QByteArray wkb( geom.
asWkb( wkbFlags ) );
 
 3215        OGRErr err = OGR_G_ImportFromWkb( ogrGeom, 
reinterpret_cast<unsigned char *
>( 
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
 
 3216        if ( err != OGRERR_NONE )
 
 3218          mErrorMessage = QObject::tr( 
"Feature geometry not imported (OGR error: %1)" )
 
 3219                          .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 3226        OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
 
 3241  for ( 
int i = 0; i < attributes.size(); i++ )
 
 3243    if ( omap.find( i ) != omap.end() )
 
 3248bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
 
 3250  if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
 
 3252    mErrorMessage = QObject::tr( 
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
 
 3262  if ( mUsingTransaction )
 
 3264    if ( OGRERR_NONE != OGR_L_CommitTransaction( 
mLayer ) )
 
 3266      QgsDebugError( QStringLiteral( 
"Error while committing transaction on OGRLayer." ) );
 
 
 3279    const QString &fileName,
 
 3280    const QString &fileEncoding,
 
 3282    const QString &driverName,
 
 3284    QString *errorMessage,
 
 3285    const QStringList &datasourceOptions,
 
 3286    const QStringList &layerOptions,
 
 3287    bool skipAttributeCreation,
 
 3288    QString *newFilename,
 
 3290    double symbologyScale,
 
 3300  if ( destCRS.
isValid() && layer )
 
 
 3326    const QString &fileName,
 
 3327    const QString &fileEncoding,
 
 3329    const QString &driverName,
 
 3331    QString *errorMessage,
 
 3332    const QStringList &datasourceOptions,
 
 3333    const QStringList &layerOptions,
 
 3334    bool skipAttributeCreation,
 
 3335    QString *newFilename,
 
 3337    double symbologyScale,
 
 
 3368  : driverName( QStringLiteral( 
"GPKG" ) )
 
 
 3376  if ( !layer || !layer->
isValid() )
 
 3383  details.sourceCrs = layer->
crs();
 
 3384  details.sourceWkbType = layer->
wkbType();
 
 3385  details.sourceFields = layer->
fields();
 
 3394  if ( details.storageType == QLatin1String( 
"ESRI Shapefile" ) )
 
 3402    details.geometryTypeScanIterator = layer->
getFeatures( req );
 
 3406  details.renderContext.setExpressionContext( details.expressionContext );
 
 3407  details.renderContext.setRendererScale( options.
symbologyScale );
 
 3409  details.shallTransform = 
false;
 
 3414    details.shallTransform = 
true;
 
 3419    details.outputCrs = details.sourceCrs;
 
 3422  details.destWkbType = details.sourceWkbType;
 
 3436    details.attributes.clear();
 
 3437  else if ( details.attributes.isEmpty() )
 
 3439    const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
 
 3440    for ( 
int idx : allAttributes )
 
 3442      QgsField fld = details.sourceFields.at( idx );
 
 3443      if ( details.providerType == QLatin1String( 
"oracle" ) && fld.
typeName().contains( QLatin1String( 
"SDO_GEOMETRY" ) ) )
 
 3445      details.attributes.append( idx );
 
 3449  if ( !details.attributes.isEmpty() )
 
 3451    for ( 
int attrIdx : std::as_const( details.attributes ) )
 
 3453      if ( details.sourceFields.exists( attrIdx ) )
 
 3455        QgsField field = details.sourceFields.at( attrIdx );
 
 3457        details.outputFields.append( field );
 
 3461        QgsDebugError( QStringLiteral( 
"No such source field with index '%1' available." ).arg( attrIdx ) );
 
 3468  if ( details.providerType == QLatin1String( 
"spatialite" ) )
 
 3470    for ( 
int i = 0; i < details.outputFields.size(); i++ )
 
 3472      if ( details.outputFields.at( i ).type() == QMetaType::Type::LongLong )
 
 3477        if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
 
 3479          details.outputFields[i].setType( QMetaType::Type::Int );
 
 3487  addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
 
 3497    bool useFilterRect = 
true;
 
 3498    if ( details.shallTransform )
 
 3509        useFilterRect = 
false;
 
 3512    if ( useFilterRect )
 
 3518    details.filterRectEngine->prepareGeometry();
 
 3520  details.sourceFeatureIterator = layer->
getFeatures( req );
 
 3539  int lastProgressReport = 0;
 
 3540  long long total = details.featureCount;
 
 3543  if ( details.providerType == QLatin1String( 
"ogr" ) && !details.dataSourceUri.isEmpty() )
 
 3545    QString srcFileName( details.providerUriParams.value( QStringLiteral( 
"path" ) ).toString() );
 
 3546    if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
 
 3550      if ( !( ( options.
driverName == QLatin1String( 
"GPKG" ) ||
 
 3551                options.
driverName == QLatin1String( 
"SpatiaLite" ) ||
 
 3552                options.
driverName == QLatin1String( 
"SQLite" ) ) &&
 
 3553              options.
layerName != details.providerUriParams.value( QStringLiteral( 
"layerName" ) ) ) )
 
 3556          *
errorMessage = QObject::tr( 
"Cannot overwrite an OGR layer in place" );
 
 3576          int newProgress = 
static_cast<int>( ( 5.0 * scanned ) / total );
 
 3577          if ( newProgress != lastProgressReport )
 
 3579            lastProgressReport = newProgress;
 
 3594  QString tempNewFilename;
 
 3595  QString tempNewLayer;
 
 3603  std::unique_ptr< QgsVectorFileWriter > writer( 
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
 
 3607    *newFilename = tempNewFilename;
 
 3610    *newLayer = tempNewLayer;
 
 3639  switch ( writer->symbologyExport() )
 
 3657  int n = 0, errors = 0;
 
 3666  writer->startRender( details.renderer.get(), details.sourceFields );
 
 3668  writer->resetMap( details.attributes );
 
 3670  writer->mFields = details.sourceFields;
 
 3674  int initialProgress = lastProgressReport;
 
 3675  while ( details.sourceFeatureIterator.nextFeature( fet ) )
 
 3686      int newProgress = 
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
 
 3687      if ( newProgress < 100 && newProgress != lastProgressReport )
 
 3689        lastProgressReport = newProgress;
 
 3694    if ( details.shallTransform )
 
 3707        const QString msg = QObject::tr( 
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
 
 3708                            .arg( fet.
id() ).arg( e.
what() );
 
 3725    if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
 
 3732          *
errorMessage = QObject::tr( 
"Feature write errors:" );
 
 3738      if ( errors > 1000 )
 
 3742          *
errorMessage += QObject::tr( 
"Stopping after %n error(s)", 
nullptr, errors );
 
 3752  writer->stopRender();
 
 3756    *
errorMessage += QObject::tr( 
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
 
 3761  bool metadataFailure = 
false;
 
 3766      {QStringLiteral( 
"path" ), tempNewFilename },
 
 3767      {QStringLiteral( 
"layerName" ), tempNewLayer }
 
 3781        metadataFailure = 
true;
 
 3792      metadataFailure = 
true;
 
 3800    const QString &fileName,
 
 3802    QString *newFilename,
 
 3806  QgsVectorFileWriter::PreparedWriterDetails details;
 
 3807  WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 
 3815    const QString &fileName,
 
 3818    QString *newFilename,
 
 3822  QgsVectorFileWriter::PreparedWriterDetails details;
 
 3823  WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 
 3832  QgsVectorFileWriter::PreparedWriterDetails details;
 
 3833  WriterError err = prepareWriteAsVectorFormat( layer, options, details );
 
 
 3842  QFileInfo fi( fileName );
 
 3843  QDir dir = fi.dir();
 
 3846  for ( 
const char *suffix : { 
".shp", 
".shx", 
".dbf", 
".prj", 
".qix", 
".qpj", 
".cpg", 
".sbn", 
".sbx", 
".idm", 
".ind" } )
 
 3848    filter << fi.completeBaseName() + suffix;
 
 3852  const auto constEntryList = dir.entryList( filter );
 
 3853  for ( 
const QString &file : constEntryList )
 
 3855    QFile f( dir.canonicalPath() + 
'/' + file );
 
 3858      QgsDebugError( QStringLiteral( 
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
 
 
 3874  QStringList driverNames;
 
 3877  for ( 
int i = 0; i < GDALGetDriverCount(); ++i )
 
 3879    GDALDriverH 
driver = GDALGetDriver( i );
 
 3886    const QString driverExtensions = GDALGetMetadataItem( 
driver, GDAL_DMD_EXTENSIONS, 
"" );
 
 3887    if ( driverExtensions.isEmpty() )
 
 3890    const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split( 
' ', Qt::SkipEmptyParts ) );
 
 3891    if ( splitExtensions.intersects( multiLayerExtensions ) )
 
 3893      driverNames << GDALGetDescription( 
driver );
 
 
 3901  static QReadWriteLock sFilterLock;
 
 3902  static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
 
 3906  const auto it = sFilters.constFind( options );
 
 3907  if ( it != sFilters.constEnd() )
 
 3911  QList< QgsVectorFileWriter::FilterFormatDetails > results;
 
 3914  int const drvCount = OGRGetDriverCount();
 
 3918  for ( 
int i = 0; i < drvCount; ++i )
 
 3920    OGRSFDriverH drv = OGRGetDriver( i );
 
 3923      const QString drvName = GDALGetDescription( drv );
 
 3927        if ( !multiLayerDrivers.contains( drvName ) )
 
 3931      GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
 
 3932      bool nonSpatialFormat = 
false;
 
 3935        nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL, 
nullptr );
 
 3938      if ( OGR_Dr_TestCapability( drv, 
"CreateDataSource" ) != 0 )
 
 3943          if ( nonSpatialFormat )
 
 3948        if ( filterString.isEmpty() )
 
 3955          globs = metadata.
glob.toLower().split( 
' ' );
 
 3961        details.
globs = globs;
 
 3970    if ( options & SortRecommended )
 
 3972      if ( a.driverName == QLatin1String( 
"GPKG" ) )
 
 3974      else if ( b.driverName == QLatin1String( 
"GPKG" ) )
 
 3976      else if ( a.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3978      else if ( b.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 3985  sFilters.insert( options, results );
 
 
 3992  QSet< QString > extensions;
 
 3994  const thread_local QRegularExpression rx( QStringLiteral( 
"\\*\\.(.*)$" ) );
 
 3998    for ( 
const QString &glob : format.globs )
 
 4000      const QRegularExpressionMatch match = rx.match( glob );
 
 4001      if ( !match.hasMatch() )
 
 4004      const QString matched = match.captured( 1 );
 
 4005      extensions.insert( matched );
 
 4009  QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
 
 4011  std::sort( extensionList.begin(), extensionList.end(), [options]( 
const QString & a, 
const QString & b ) -> 
bool 
 4013    if ( options & SortRecommended )
 
 4015      if ( a == QLatin1String( 
"gpkg" ) )
 
 4017      else if ( b == QLatin1String( 
"gpkg" ) )
 
 4019      else if ( a == QLatin1String( 
"shp" ) )
 
 4021      else if ( b == QLatin1String( 
"shp" ) )
 
 4025    return a.toLower().localeAwareCompare( b.toLower() ) < 0;
 
 4028  return extensionList;
 
 
 4033  QList< QgsVectorFileWriter::DriverDetails > results;
 
 4036  const int drvCount = OGRGetDriverCount();
 
 4040  QStringList writableDrivers;
 
 4041  for ( 
int i = 0; i < drvCount; ++i )
 
 4043    OGRSFDriverH drv = OGRGetDriver( i );
 
 4046      const QString drvName = GDALGetDescription( drv );
 
 4050        if ( !multiLayerDrivers.contains( drvName ) )
 
 4058        if ( drvName == QLatin1String( 
"ODS" ) || drvName == QLatin1String( 
"XLSX" ) || drvName == QLatin1String( 
"XLS" ) )
 
 4062      if ( drvName == QLatin1String( 
"ESRI Shapefile" ) )
 
 4064        writableDrivers << QStringLiteral( 
"DBF file" );
 
 4066      if ( OGR_Dr_TestCapability( drv, 
"CreateDataSource" ) != 0 )
 
 4069        if ( drvName == QLatin1String( 
"MapInfo File" ) )
 
 4071          writableDrivers << QStringLiteral( 
"MapInfo MIF" );
 
 4073        else if ( drvName == QLatin1String( 
"SQLite" ) )
 
 4080          QString option = QStringLiteral( 
"SPATIALITE=YES" );
 
 4081          char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ), 
nullptr };
 
 4082          OGRSFDriverH poDriver;
 
 4084          poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
 
 4087            gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral( 
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
 
 4090              writableDrivers << QStringLiteral( 
"SpatiaLite" );
 
 4091              OGR_Dr_DeleteDataSource( poDriver, QStringLiteral( 
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
 
 4094          CPLFree( options[0] );
 
 4096        writableDrivers << drvName;
 
 4101  results.reserve( writableDrivers.count() );
 
 4102  for ( 
const QString &drvName : std::as_const( writableDrivers ) )
 
 4116    if ( options & SortRecommended )
 
 4118      if ( a.driverName == QLatin1String( 
"GPKG" ) )
 
 4120      else if ( b.driverName == QLatin1String( 
"GPKG" ) )
 
 4122      else if ( a.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 4124      else if ( b.driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 4128    return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
 
 
 4135  QString ext = extension.trimmed();
 
 4136  if ( ext.isEmpty() )
 
 4139  if ( ext.startsWith( 
'.' ) )
 
 4143  int const drvCount = GDALGetDriverCount();
 
 4145  for ( 
int i = 0; i < drvCount; ++i )
 
 4147    GDALDriverH drv = GDALGetDriver( i );
 
 4153        QString drvName = GDALGetDriverShortName( drv );
 
 4154        QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, 
nullptr ) ).split( 
' ' );
 
 4156        const auto constDriverExtensions = driverExtensions;
 
 4157        for ( 
const QString &
driver : constDriverExtensions )
 
 4159          if ( 
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
 
 
 4170  QString filterString;
 
 4174    if ( !filterString.isEmpty() )
 
 4175      filterString += QLatin1String( 
";;" );
 
 4177    filterString += details.filterString;
 
 4179  return filterString;
 
 
 4188  return QStringLiteral( 
"%1 (%2 %3)" ).arg( metadata.
trLongName,
 
 4189         metadata.
glob.toLower(),
 
 4190         metadata.
glob.toUpper() );
 
 
 4195  if ( codecName == QLatin1String( 
"System" ) )
 
 4196    return QStringLiteral( 
"LDID/0" );
 
 4198  const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString( 
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
 
 4199  const QRegularExpressionMatch match = re.match( codecName );
 
 4200  if ( match.hasMatch() )
 
 4202    QString 
c = match.captured( 2 ).remove( 
'-' );
 
 4204    ( void ) 
c.toInt( &isNumber );
 
 
 4232  OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
 
 4233  OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
 
 4236  int nTotalLevels = 0;
 
 4238  QgsSymbolList::iterator symbolIt = symbolList.begin();
 
 4239  for ( ; symbolIt != symbolList.end(); ++symbolIt )
 
 4241    double mmsf = mmScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
 
 4242    double musf = mapUnitScaleFactor( 
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
 
 4244    int nLevels = ( *symbolIt )->symbolLayerCount();
 
 4245    for ( 
int i = 0; i < nLevels; ++i )
 
 4247      mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
 
 4248      OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
 
 4249                       ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
 
 4253  OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
 
 4259  if ( !details.renderer )
 
 4264  QHash< QgsSymbol *, QList<QgsFeature> > features;
 
 4273  startRender( details.renderer.get(), details.sourceFields );
 
 4293        QString msg = QObject::tr( 
"Failed to transform, writing stopped. (Exception: %1)" )
 
 4304    featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
 
 4305    if ( !featureSymbol )
 
 4310    QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
 
 4311    if ( it == features.end() )
 
 4313      it = features.insert( featureSymbol, QList<QgsFeature>() );
 
 4315    it.value().append( fet );
 
 4320  QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
 
 4321  for ( 
int i = 0; i < symbols.count(); i++ )
 
 4327      if ( level < 0 || level >= 1000 ) 
 
 4330      while ( level >= levels.count() ) 
 
 4332      levels[level].append( item );
 
 4337  int nTotalFeatures = 0;
 
 4340  for ( 
int l = 0; l < levels.count(); l++ )
 
 4343    for ( 
int i = 0; i < level.count(); i++ )
 
 4346      QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
 
 4347      if ( levelIt == features.end() )
 
 4353      double mmsf = mmScaleFactor( 
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
 
 4354      double musf = mapUnitScaleFactor( 
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
 
 4356      int llayer = item.
layer();
 
 4357      QList<QgsFeature> &featureList = levelIt.value();
 
 4358      QList<QgsFeature>::iterator featureIt = featureList.begin();
 
 4359      for ( ; featureIt != featureList.end(); ++featureIt )
 
 4369        QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
 
 4370        if ( !styleString.isEmpty() )
 
 4372          OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
 
 4373          if ( !writeFeature( 
mLayer, ogrFeature.get() ) )
 
 4386    *
errorMessage += QObject::tr( 
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
 
 4403      return 1000 / scale;
 
 4420      return scale / 1000;
 
 4428  mRenderer = createSymbologyRenderer( sourceRenderer );
 
 4434  mRenderer->startRender( mRenderContext,  fields );
 
 4437void QgsVectorFileWriter::stopRender()
 
 4444  mRenderer->stopRender( mRenderContext );
 
 4447std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer( 
QgsFeatureRenderer *sourceRenderer )
 const 
 4460  if ( !sourceRenderer )
 
 4465  return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
 
 4472    const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
 
 4473    for ( 
const QString &attr : rendererAttributes )
 
 4478        attList.append( index );
 
 4484QStringList QgsVectorFileWriter::concatenateOptions( 
const QMap<QString, QgsVectorFileWriter::Option *> &options )
 
 4487  QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
 
 4489  for ( it = options.constBegin(); it != options.constEnd(); ++it )
 
 4492    switch ( option->
type )
 
 4499          list.append( QStringLiteral( 
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
 
 4509          list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
 
 4519          list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
 
 4526        if ( opt && !opt->
mValue.isEmpty() )
 
 4528          list.append( QStringLiteral( 
"%1=%2" ).arg( it.key(), opt->
mValue ) );
 
 4539  OGRSFDriverH hDriver = 
nullptr;
 
 4543  const QString drvName = GDALGetDescription( hDriver );
 
 4545  if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
 
 4550    if ( !( drvName == QLatin1String( 
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
 
 4553  if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
 
 4557  int layer_count = OGR_DS_GetLayerCount( hDS.get() );
 
 4560    OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 4563      if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
 
 4566        if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
 
 
 4577    const QString &layerNameIn )
 
 4579  OGRSFDriverH hDriver = 
nullptr;
 
 4584  QString layerName( layerNameIn );
 
 4585  if ( layerName.isEmpty() )
 
 4586    layerName = QFileInfo( datasetName ).baseName();
 
 4588  return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
 
 
 4593    const QString &layerName,
 
 4597  OGRSFDriverH hDriver = 
nullptr;
 
 4601  OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
 
 4607  OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
 
 4608  const auto constAttributes = attributes;
 
 4609  for ( 
int idx : constAttributes )
 
 4612    if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
 
 
@ FieldComments
Writer can support field comments.
 
@ FieldAliases
Writer can support field aliases.
 
DistanceUnit
Units of distance.
 
QFlags< VectorFileWriterCapability > VectorFileWriterCapabilities
Capabilities supported by a QgsVectorFileWriter object.
 
RenderUnit
Rendering size units.
 
@ Millimeters
Millimeters.
 
WkbType
The WKB type describes the number of dimensions a geometry has.
 
@ MultiPolygon25D
MultiPolygon25D.
 
@ GeometryCollectionZ
GeometryCollectionZ.
 
@ MultiLineString
MultiLineString.
 
@ MultiPolygonZ
MultiPolygonZ.
 
FeatureSymbologyExport
Options for exporting features considering their symbology.
 
@ PerFeature
Keeps the number of features and export symbology per feature.
 
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels)
 
@ NoSymbology
Export only data.
 
@ Reverse
Reverse/inverse transform (from destination to source)
 
Provides common functionality for database based connections.
 
virtual QgsFieldDomain * fieldDomain(const QString &name) const
Returns the field domain with the specified name from the provider.
 
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
 
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
 
QFlags< WkbFlag > WkbFlags
 
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
 
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
 
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
 
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN.
 
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
 
Represents a coordinate reference system (CRS).
 
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
 
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
 
Qgis::DistanceUnit mapUnits
 
Contains information about the context in which a coordinate transform is executed.
 
Custom exception class for Coordinate Reference System related exceptions.
 
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
 
Stores the component parts of a data source URI (e.g.
 
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
 
Wrapper for iterator of features from vector data provider or vector layer.
 
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
 
Abstract base class for all 2D vector feature renderers.
 
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
 
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
 
bool usingSymbolLevels() const
 
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
 
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
 
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
 
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
 
Wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
 
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
 
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
 
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
 
QFlags< SinkFlag > SinkFlags
 
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
 
bool hasGeometry() const
Returns true if the feature has an associated geometry.
 
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
 
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
 
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
QString domainName() const
Returns the associated field domain name, for providers which support field domains.
 
@ ConstraintNotNull
Field may not be null.
 
@ ConstraintUnique
Field must have a unique value.
 
Encapsulate a field in an attribute table or data source.
 
QString typeName() const
Gets the field type.
 
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
 
void setName(const QString &name)
Set the field name.
 
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
 
QgsFieldConstraints constraints
 
Container of fields for a vector layer.
 
int size() const
Returns number of items.
 
void clear()
Removes all fields.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
 
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
 
A geometry is the spatial representation of a feature.
 
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
 
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
 
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
 
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
 
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
 
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
 
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
 
Sets the current locale to the c locale for the lifetime of the object.
 
static void warning(const QString &msg)
Goes to qWarning.
 
static QgsAbstractDatabaseProviderConnection * databaseConnection(const QgsMapLayer *layer)
Creates and returns the (possibly nullptr) database connection for a layer.
 
QString providerType() const
Returns the provider type (provider key) for this layer.
 
QgsCoordinateReferenceSystem crs
 
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Custom exception class which is raised when an operation is not supported.
 
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
 
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
 
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
 
Custom exception class for provider connection related exceptions.
 
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
 
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
 
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
 
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage)
Saves metadata to the layer corresponding to the specified uri.
 
A convenience class that simplifies locking and unlocking QReadWriteLocks.
 
void changeMode(Mode mode)
Change the mode of the lock to mode.
 
A rectangle specified with double values.
 
Contains information about the context of a rendering operation.
 
QgsExpressionContext & expressionContext()
Gets the expression context.
 
void setRendererScale(double scale)
Sets the renderer map scale.
 
Stores settings for use within QGIS.
 
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
 
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
 
Represents a symbol level during vector rendering operations.
 
int layer() const
The layer of this symbol level.
 
QgsSymbol * symbol() const
The symbol of this symbol level.
 
Abstract base class for all rendered symbols.
 
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
 
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
 
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
 
An available option for configuring file writing for a particular output format, presenting an boolea...
 
Interface to convert raw field values to their user-friendly values.
 
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
 
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
 
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
 
A hidden option for file writing for a particular output format.
 
An available option for configuring file writing for a particular output format, presenting an intege...
 
Describes an available option for configuring file writing for a particular output format.
 
QgsVectorFileWriter::OptionType type
 
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
 
QString fileEncoding
Encoding to use.
 
bool forceMulti
Sets to true to force creation of multipart geometries.
 
QString driverName
OGR driver to use.
 
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
 
QStringList attributesExportNames
Attributes export names.
 
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
 
QString layerName
Layer name. If let empty, it will be derived from the filename.
 
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
 
bool includeConstraints
Set to true to transfer field constraints to the exported vector file.
 
const QgsAbstractDatabaseProviderConnection * sourceDatabaseProviderConnection
Source database provider connection, for field domains.
 
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
 
QStringList layerOptions
List of OGR layer creation options.
 
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
 
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
 
Qgis::FeatureSymbologyExport symbologyExport
Symbology to export.
 
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
 
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
 
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
 
bool onlySelectedFeatures
Write only selected features of layer.
 
QgsVectorFileWriter::FieldNameSource fieldNameSource
Source for exported field names.
 
bool skipAttributeCreation
Only write geometries.
 
bool setFieldDomains
Set to true to transfer field domains to the exported vector file.
 
double symbologyScale
Scale of symbology.
 
QStringList datasourceOptions
List of OGR data source creation options.
 
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
 
An available option for configuring file writing for a particular output format, presenting a choice ...
 
An available option for configuring file writing for a particular output format, presenting a freefor...
 
A convenience class for writing vector layers to disk based formats (e.g.
 
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
 
Qgis::FeatureSymbologyExport mSymbologyExport
 
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
 
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
 
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
 
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
 
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
 
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
 
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
 
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
 
Qgis::WkbType mWkbType
Geometry type which is being used.
 
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
 
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
 
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
 
@ ErrAttributeTypeUnsupported
 
@ Canceled
Writing was interrupted by manual cancellation.
 
@ ErrAttributeCreationFailed
 
@ ErrSavingMetadata
Metadata saving failed.
 
gdal::ogr_datasource_unique_ptr mDS
 
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
 
OGRGeometryH createEmptyGeometry(Qgis::WkbType wkbType)
 
QString mOgrDriverLongName
 
QFlags< EditionCapability > EditionCapabilities
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
 
~QgsVectorFileWriter() override
Close opened shapefile for writing.
 
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
 
double symbologyScale() const
Returns the reference scale for output.
 
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
 
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
 
Qgis::VectorFileWriterCapabilities capabilities() const
Returns the capabilities supported by the writer.
 
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
 
OGRSpatialReferenceH mOgrRef
 
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
 
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
 
QString driver() const
Returns the GDAL (short) driver name associated with the output file.
 
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
 
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
 
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, Qgis::WkbType overrideGeometryType=Qgis::WkbType::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
 
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
 
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
 
@ SupportsMultipleLayers
Filter to only formats which support multiple layers.
 
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
 
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
 
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
 
QString driverLongName() const
Returns the GDAL long driver name associated with the output file.
 
QFlags< VectorFormatOption > VectorFormatOptions
 
WriterError mError
Contains error value if construction was not successful.
 
Qgis::FeatureSymbologyExport symbologyExport() const
Returns the feature symbology export handling for the writer.
 
FieldNameSource
Source for exported field names.
 
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
 
@ Original
Use original field names.
 
bool mIncludeConstraints
Whether to transfer field constraints to output.
 
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
 
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
 
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
 
bool mSetFieldDomains
Whether to set field domains to output.
 
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
 
FieldValueConverter * mFieldValueConverter
Field value converter.
 
QString errorMessage() const
Retrieves error message.
 
void setSymbologyScale(double scale)
Set reference scale for output.
 
static OGRwkbGeometryType ogrTypeFromWkbType(Qgis::WkbType type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
 
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
 
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
 
ActionOnExistingFile
Enumeration to describe how to handle existing files.
 
@ CreateOrOverwriteLayer
Create or overwrite layer.
 
@ CreateOrOverwriteFile
Create or overwrite file.
 
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
 
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
 
Represents a vector layer which manages a vector based dataset.
 
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
 
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
 
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
 
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
 
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
 
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
 
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
 
static Qgis::WkbType to25D(Qgis::WkbType type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
 
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
 
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
 
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
 
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
 
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
 
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
 
static Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
 
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
 
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
 
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
#define Q_NOWARN_DEPRECATED_POP
 
#define Q_NOWARN_DEPRECATED_PUSH
 
QList< QgsFeature > QgsFeatureList
 
QList< int > QgsAttributeList
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
QList< QgsSymbolLevel > QgsSymbolLevelOrder
 
QList< QgsSymbolLevelItem > QgsSymbolLevel
 
QList< QgsSymbol * > QgsSymbolList
 
QStringList multiLayerFormats()
 
Details of available driver formats.
 
QString longName
Descriptive, user friendly name for the driver.
 
QString driverName
Unique driver name.