40#include "qgsogrproviderutils.h" 
   42#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
   53#include <QJsonDocument> 
   58#include <QRegularExpression> 
   60#include "ogr_srs_api.h" 
   65  OGR_DS_Destroy( source );
 
 
   71  OGR_G_DestroyGeometry( geometry );
 
 
   76  OGR_Fld_Destroy( definition );
 
 
   81  OGR_F_Destroy( feature );
 
 
   98  CPLPushErrorHandler( CPLQuietErrorHandler );
 
   99  GDALDeleteDataset( driver, path.toUtf8().constData() );
 
  100  CPLPopErrorHandler();
 
 
  111  GDALDestroyWarpOptions( options );
 
 
  114#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
  117  GDALDestroyRelationship( relationship );
 
 
  121static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt, 
int nTZFlag )
 
  128  else if ( nTZFlag == 1 )
 
  130    dt.setTimeSpec( Qt::LocalTime );
 
  132  else if ( nTZFlag == 100 )
 
  134    dt.setTimeSpec( Qt::UTC );
 
  140    dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
 
  146  if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
 
  152      return value->Integer;
 
  155      return value->Integer64;
 
  162      return QString::fromUtf8( value->String );
 
  165      return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
 
  169      float secondsPart = 0;
 
  170      float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  171      return QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
 
  176      float secondsPart = 0;
 
  177      float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  178      QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
 
  179                                QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
 
  180      setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
 
  186      Q_ASSERT_X( 
false, 
"QgsOgrUtils::OGRFieldtoVariant", 
"OFTBinary type not supported" );
 
  192      res.reserve( value->IntegerList.nCount );
 
  193      for ( 
int i = 0; i < value->IntegerList.nCount; ++i )
 
  194        res << value->IntegerList.paList[ i ];
 
  198    case OFTInteger64List:
 
  201      res.reserve( value->Integer64List.nCount );
 
  202      for ( 
int i = 0; i < value->Integer64List.nCount; ++i )
 
  203        res << value->Integer64List.paList[ i ];
 
  210      res.reserve( value->RealList.nCount );
 
  211      for ( 
int i = 0; i < value->RealList.nCount; ++i )
 
  212        res << value->RealList.paList[ i ];
 
  217    case OFTWideStringList:
 
  220      res.reserve( value->StringList.nCount );
 
  221      for ( 
int i = 0; i < value->StringList.nCount; ++i )
 
  222        res << QString::fromUtf8( value->StringList.paList[ i ] );
 
 
  231  if ( datetime.timeSpec() == Qt::LocalTime )
 
  233  return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
 
 
  238  std::unique_ptr< OGRField > res = std::make_unique< OGRField >();
 
  240  switch ( value.userType() )
 
  242    case QMetaType::Type::UnknownType:
 
  243      OGR_RawField_SetUnset( res.get() );
 
  245    case QMetaType::Type::Bool:
 
  247      const int val = value.toBool() ? 1 : 0;
 
  248      if ( type == OFTInteger )
 
  250      else if ( type == OFTInteger64 )
 
  251        res->Integer64 = val;
 
  252      else if ( type == OFTReal )
 
  261    case QMetaType::Type::Int:
 
  263      const int val = value.toInt();
 
  264      if ( type == OFTInteger )
 
  266      else if ( type == OFTInteger64 )
 
  267        res->Integer64 = val;
 
  268      else if ( type == OFTReal )
 
  277    case QMetaType::Type::LongLong:
 
  279      const qint64 val = value.toLongLong();
 
  280      if ( type == OFTInteger )
 
  282        if ( val <= std::numeric_limits<int>::max() &&
 
  283             val >= std::numeric_limits<int>::min() )
 
  285          res->Integer = 
static_cast<int>( val );
 
  293      else if ( type == OFTInteger64 )
 
  294        res->Integer64 = val;
 
  295      else if ( type == OFTReal )
 
  297        res->Real = 
static_cast<double>( val );
 
  301        QgsDebugError( 
"Unsupported output data type for LongLong" );
 
  306    case QMetaType::Type::Double:
 
  308      double val = value.toDouble();
 
  309      if ( type == OFTInteger )
 
  311        if ( val <= std::numeric_limits<int>::max() &&
 
  312             val >= std::numeric_limits<int>::min() )
 
  314          res->Integer = 
static_cast<int>( val );
 
  322      else if ( type == OFTInteger64 )
 
  324        if ( val <= 
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
 
  325             val >= 
static_cast<double>( std::numeric_limits<qint64>::min() ) )
 
  327          res->Integer64 = 
static_cast<qint64
>( val );
 
  335      else if ( type == OFTReal )
 
  341        QgsDebugError( 
"Unsupported output data type for LongLong" );
 
  346    case QMetaType::Type::QChar:
 
  347    case QMetaType::Type::QString:
 
  349      if ( type == OFTString )
 
  350        res->String = CPLStrdup( value.toString().toUtf8().constData() );
 
  358    case QMetaType::Type::QDate:
 
  360      if ( type == OFTDate )
 
  362        const QDate date = value.toDate();
 
  363        res->Date.Day = date.day();
 
  364        res->Date.Month = date.month();
 
  365        res->Date.Year = 
static_cast<GInt16
>( date.year() );
 
  366        res->Date.TZFlag = 0;
 
  375    case QMetaType::Type::QTime:
 
  377      if ( type == OFTTime )
 
  379        const QTime time = value.toTime();
 
  380        res->Date.Hour = time.hour();
 
  381        res->Date.Minute = time.minute();
 
  382        res->Date.Second = 
static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 );
 
  383        res->Date.TZFlag = 0;
 
  392    case QMetaType::Type::QDateTime:
 
  394      if ( type == OFTDateTime )
 
  396        const QDateTime dt = value.toDateTime();
 
  397        const QDate date = dt.date();
 
  398        res->Date.Day = date.day();
 
  399        res->Date.Month = date.month();
 
  400        res->Date.Year = 
static_cast<GInt16
>( date.year() );
 
  401        const QTime time = dt.time();
 
  402        res->Date.Hour = time.hour();
 
  403        res->Date.Minute = time.minute();
 
  404        res->Date.Second = 
static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 );
 
  405        res->Date.TZFlag = OGRTZFlagFromQt( dt );
 
  409        QgsDebugError( 
"Unsupported output data type for DateTime" );
 
  416      QgsDebugError( 
"Unhandled variant type in variantToOGRField" );
 
  417      OGR_RawField_SetUnset( res.get() );
 
 
  433  feature.
setId( OGR_F_GetFID( ogrFet ) );
 
  436  if ( !readOgrFeatureGeometry( ogrFet, feature ) )
 
  441  if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
 
 
  456  int fieldCount = OGR_F_GetFieldCount( ogrFet );
 
  457  for ( 
int i = 0; i < fieldCount; ++i )
 
  459    OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
 
  466    QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
 
  467    QMetaType::Type varType;
 
  468    switch ( OGR_Fld_GetType( fldDef ) )
 
  471        if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
 
  472          varType = QMetaType::Type::Bool;
 
  474          varType = QMetaType::Type::Int;
 
  477        varType = QMetaType::Type::LongLong;
 
  480        varType = QMetaType::Type::Double;
 
  483        varType = QMetaType::Type::QDate;
 
  486        varType = QMetaType::Type::QTime;
 
  489        varType = QMetaType::Type::QDateTime;
 
  492        if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
 
  493          varType = QMetaType::Type::QVariantMap;
 
  495          varType = QMetaType::Type::QString;
 
  498        varType = QMetaType::Type::QString; 
 
 
  508  if ( attIndex < 0 || attIndex >= fields.
count() )
 
  516  return getOgrFeatureAttribute( ogrFet, field, attIndex, encoding, ok );
 
 
  521  if ( !ogrFet || attIndex < 0 )
 
  528  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
 
  535    QgsDebugError( QStringLiteral( 
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
 
  544  if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
 
  546    switch ( field.
type() )
 
  548      case QMetaType::Type::QString:
 
  551          value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  553          value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  558        if ( value.isNull() )
 
  559          value = QVariant( QStringLiteral( 
"" ) ); 
 
  564      case QMetaType::Type::Int:
 
  565        value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
 
  567      case QMetaType::Type::Bool:
 
  568        value = QVariant( 
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
 
  570      case QMetaType::Type::LongLong:
 
  571        value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
 
  573      case QMetaType::Type::Double:
 
  574        value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
 
  576      case QMetaType::Type::QDate:
 
  577      case QMetaType::Type::QDateTime:
 
  578      case QMetaType::Type::QTime:
 
  580        int year, month, day, hour, minute, tzf;
 
  582        float secondsPart = 0;
 
  584        OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
 
  585        float millisecondPart = std::modf( second, &secondsPart );
 
  587        if ( field.
type() == QMetaType::Type::QDate )
 
  588          value = QDate( year, month, day );
 
  589        else if ( field.
type() == QMetaType::Type::QTime )
 
  590          value = QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
 
  593          QDateTime dt = QDateTime( QDate( year, month, day ),
 
  594                                    QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
 
  595          setQTTimeZoneFromOGRTZFlag( dt, tzf );
 
  601      case QMetaType::Type::QByteArray:
 
  604        const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
 
  608        QByteArray ba = QByteArray::fromRawData( 
reinterpret_cast<const char *
>( b ), size );
 
  615      case QMetaType::Type::QStringList:
 
  618        char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  619        const int count = CSLCount( lst );
 
  622          list.reserve( count );
 
  623          for ( 
int i = 0; i < count; i++ )
 
  626              list << encoding->toUnicode( lst[i] );
 
  628              list << QString::fromUtf8( lst[i] );
 
  635      case QMetaType::Type::QVariantList:
 
  639          case QMetaType::Type::QString:
 
  642            char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  643            const int count = CSLCount( lst );
 
  646              list.reserve( count );
 
  647              for ( 
int i = 0; i < count; i++ )
 
  650                  list << encoding->toUnicode( lst[i] );
 
  652                  list << QString::fromUtf8( lst[i] );
 
  659          case QMetaType::Type::Int:
 
  663            const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
 
  666              list.reserve( count );
 
  667              for ( 
int i = 0; i < count; i++ )
 
  676          case QMetaType::Type::Double:
 
  680            const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
 
  683              list.reserve( count );
 
  684              for ( 
int i = 0; i < count; i++ )
 
  693          case QMetaType::Type::LongLong:
 
  697            const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
 
  700              list.reserve( count );
 
  701              for ( 
int i = 0; i < count; i++ )
 
  712            Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
  721      case QMetaType::Type::QVariantMap:
 
  726          value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  728          value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  732        Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
 
  755  for ( 
int idx = 0; idx < fields.
count(); ++idx )
 
  757    QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
 
 
  771  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
 
  775    feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
 
 
  785  OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
 
  786  return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
 
 
  791  std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
 
  793  const int count = OGR_G_GetGeometryCount( geom );
 
  794  mp->reserve( count );
 
  795  for ( 
int i = 0; i < count; ++i )
 
 
  807  int count = OGR_G_GetPointCount( geom );
 
  808  QVector< double > x( count );
 
  809  QVector< double > y( count );
 
  811  double *pz = 
nullptr;
 
  817  double *pm = 
nullptr;
 
  824  OGR_G_GetPointsZM( geom, x.data(), 
sizeof( 
double ), y.data(), 
sizeof( 
double ), pz, 
sizeof( 
double ), pm, 
sizeof( 
double ) );
 
 
  831  std::unique_ptr< QgsMultiLineString > mp = std::make_unique< QgsMultiLineString >();
 
  833  const int count = OGR_G_GetGeometryCount( geom );
 
  834  mp->reserve( count );
 
  835  for ( 
int i = 0; i < count; ++i )
 
 
  845  std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
 
  847  const int count = OGR_G_GetGeometryCount( geom );
 
  853  for ( 
int i = 1; i < count; ++i )
 
 
  863  std::unique_ptr< QgsMultiPolygon > polygon = std::make_unique< QgsMultiPolygon >();
 
  865  const int count = OGR_G_GetGeometryCount( geom );
 
  866  polygon->reserve( count );
 
  867  for ( 
int i = 0; i < count; ++i )
 
 
  877  switch ( ogrGeomType )
 
 
  966  const auto ogrGeomType = OGR_G_GetGeometryType( geom );
 
  967  Qgis::WkbType wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
 
 1009  if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
 
 1012    if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
 
 1013         wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
 
 1015      auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
 
 1016      auto ret = ogrGeometryToQgsGeometry( newGeom );
 
 1017      OGR_G_DestroyGeometry( newGeom );
 
 1023  int memorySize = OGR_G_WkbSize( geom );
 
 1024  unsigned char *wkb = 
new unsigned char[memorySize];
 
 1028  uint32_t origGeomType;
 
 1029  memcpy( &origGeomType, wkb + 1, 
sizeof( uint32_t ) );
 
 1030  bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
 
 1031  bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
 
 1034  if ( origGeomType % 1000 == 16 ) 
 
 1037    int nDims = 2 + hasZ + hasM;
 
 1040    unsigned char *wkbptr = wkb;
 
 1046    memcpy( wkbptr, &newMultiType, 
sizeof( uint32_t ) );
 
 1051    memcpy( &numGeoms, wkb + 5, 
sizeof( uint32_t ) );
 
 1055    for ( uint32_t i = 0; i < numGeoms; ++i )
 
 1061      memcpy( wkbptr, &newSingleType, 
sizeof( uint32_t ) );
 
 1062      wkbptr += 
sizeof( uint32_t );
 
 1066      memcpy( &nRings, wkbptr, 
sizeof( uint32_t ) );
 
 1067      wkbptr += 
sizeof( uint32_t );
 
 1069      for ( uint32_t j = 0; j < nRings; ++j )
 
 1072        memcpy( &nPoints, wkbptr, 
sizeof( uint32_t ) );
 
 1073        wkbptr += 
sizeof( uint32_t ) + 
sizeof( 
double ) * nDims * nPoints;
 
 1077  else if ( origGeomType % 1000 == 15 ) 
 
 1082    memcpy( wkb + 1, &newType, 
sizeof( uint32_t ) );
 
 
 1093  if ( 
string.isEmpty() )
 
 1096  QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
 1099  QByteArray ba = 
string.toUtf8();
 
 1100  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
 1101                                    static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
 1106    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1110  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 1114    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1119  while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
 1121    QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
 
 1127  VSIUnlink( randomFileName.toUtf8().constData() );
 
 
 1135  if ( 
string.isEmpty() )
 
 1138  QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
 1141  QByteArray ba = 
string.toUtf8();
 
 1142  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
 1143                                    static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
 1148    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1152  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 1156    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1162  if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
 1164    fields = readOgrFields( oFeat.get(), encoding );
 
 1168  VSIUnlink( randomFileName.toUtf8().constData() );
 
 
 1177  QStringList strings;
 
 1179  for ( 
qgssize i = 0; stringList[i]; ++i )
 
 1181    strings.
append( QString::fromUtf8( stringList[i] ) );
 
 
 1192  char *pszWkt = 
nullptr;
 
 1193  const QByteArray multiLineOption = QStringLiteral( 
"MULTILINE=NO" ).toLocal8Bit();
 
 1194  const QByteArray formatOption = QStringLiteral( 
"FORMAT=WKT2" ).toLocal8Bit();
 
 1195  const char *
const options[] = {multiLineOption.constData(), formatOption.constData(), 
nullptr};
 
 1196  OSRExportToWktEx( srs, &pszWkt, options );
 
 1198  const QString res( pszWkt );
 
 
 1205  const QString wkt = OGRSpatialReferenceToWkt( srs );
 
 1206  if ( wkt.isEmpty() )
 
 1209  const char *authorityName = OSRGetAuthorityName( srs, 
nullptr );
 
 1210  const char *authorityCode = OSRGetAuthorityCode( srs, 
nullptr );
 
 1212  if ( authorityName && authorityCode )
 
 1214    QString authId = QString( authorityName ) + 
':' + QString( authorityCode );
 
 1217    if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
 
 1218         OSRIsSame( srs, ogrSrsTmp ) )
 
 1223    OSRDestroySpatialReference( ogrSrsTmp );
 
 1228#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
 1229  const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
 
 1230  if ( coordinateEpoch > 0 )
 
 
 1248    if ( !authId.isEmpty() )
 
 1250      ogrSrs = OSRNewSpatialReference( 
nullptr );
 
 1251      if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
 
 1255        if ( ogrSrsFromWkt )
 
 1257          if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
 
 1259            OSRDestroySpatialReference( ogrSrs );
 
 1260            ogrSrs = ogrSrsFromWkt;
 
 1264            OSRDestroySpatialReference( ogrSrsFromWkt );
 
 1270        OSRDestroySpatialReference( ogrSrs );
 
 1276      ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
 
 1280      OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
 
 1281#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
 
 1296  const QString cpgEncoding = readShapefileEncodingFromCpg( path );
 
 1297  if ( !cpgEncoding.isEmpty() )
 
 1300  return readShapefileEncodingFromLdid( path );
 
 
 1306  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1307  return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_CPG" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 
 1313  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1314  return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_LDID" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 
 1321  char **papszStyleString = CSLTokenizeString2( 
string.toUtf8().constData(), 
";",
 
 1323                            | CSLT_PRESERVEQUOTES
 
 1324                            | CSLT_PRESERVEESCAPES );
 
 1325  for ( 
int i = 0; papszStyleString[i] != 
nullptr; ++i )
 
 1331    const thread_local QRegularExpression sToolPartRx( QStringLiteral( 
"^(.*?)\\((.*)\\)$" ) );
 
 1332    const QString stylePart( papszStyleString[i] );
 
 1333    const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
 
 1334    if ( !match.hasMatch() )
 
 1337    const QString tool = match.captured( 1 );
 
 1338    const QString params = match.captured( 2 );
 
 1340    char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(), 
",", CSLT_HONOURSTRINGS
 
 1341                         | CSLT_PRESERVEESCAPES );
 
 1343    QVariantMap toolParts;
 
 1344    const thread_local QRegularExpression sToolParamRx( QStringLiteral( 
"^(.*?):(.*)$" ) );
 
 1345    for ( 
int j = 0; papszTokens[j] != 
nullptr; ++j )
 
 1347      const QString toolPart( papszTokens[j] );
 
 1348      const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
 
 1349      if ( !match.hasMatch() )
 
 1353      toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
 
 1355    CSLDestroy( papszTokens );
 
 1358    styles.insert( tool.toLower(), toolParts );
 
 1360  CSLDestroy( papszStyleString );
 
 
 1366  const QVariantMap styles = parseStyleString( 
string );
 
 1368  auto convertSize = []( 
const QString & size, 
double & value, 
Qgis::RenderUnit & unit )->
bool 
 1370    const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
 
 1371    const QRegularExpressionMatch match = sUnitRx.match( size );
 
 1372    if ( match.hasMatch() )
 
 1374      value = match.captured( 1 ).toDouble();
 
 1375      const QString unitString = match.captured( 2 );
 
 1376      if ( unitString.compare( QLatin1String( 
"px" ), Qt::CaseInsensitive ) == 0 )
 
 1380        static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
 
 1381        static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
 
 1383        value *= PX_TO_PT_FACTOR;
 
 1386      else if ( unitString.compare( QLatin1String( 
"pt" ), Qt::CaseInsensitive ) == 0 )
 
 1391      else if ( unitString.compare( QLatin1String( 
"mm" ), Qt::CaseInsensitive ) == 0 )
 
 1396      else if ( unitString.compare( QLatin1String( 
"cm" ), Qt::CaseInsensitive ) == 0 )
 
 1402      else if ( unitString.compare( QLatin1String( 
"in" ), Qt::CaseInsensitive ) == 0 )
 
 1407      else if ( unitString.compare( QLatin1String( 
"g" ), Qt::CaseInsensitive ) == 0 )
 
 1412      QgsDebugError( QStringLiteral( 
"Unknown unit %1" ).arg( unitString ) );
 
 1416      QgsDebugError( QStringLiteral( 
"Could not parse style size %1" ).arg( size ) );
 
 1421  auto convertColor = []( 
const QString & string ) -> QColor
 
 1423    if ( 
string.isEmpty() )
 
 1426    const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral( 
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
 
 1427    const QRegularExpressionMatch match = sColorWithAlphaRx.match( 
string );
 
 1428    if ( match.hasMatch() )
 
 1431      return QColor( QStringLiteral( 
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
 
 1435      return QColor( 
string );
 
 1439  auto convertPen = [&convertColor, &convertSize, string]( 
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
 
 1441    QColor color = convertColor( lineStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1445    convertSize( lineStyle.value( QStringLiteral( 
"w" ) ).toString(), lineWidth, lineWidthUnit );
 
 1448    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-pen-(\\d+)" ) );
 
 1449    const QRegularExpressionMatch match = sMapInfoId.match( 
string );
 
 1450    if ( match.hasMatch() )
 
 1452      const int penId = match.captured( 1 ).toInt();
 
 1459    std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
 
 1460    simpleLine->setWidthUnit( lineWidthUnit );
 
 1463    const QString pattern = lineStyle.value( QStringLiteral( 
"p" ) ).toString();
 
 1464    if ( !pattern.isEmpty() )
 
 1466      const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
 
 1467      const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
 
 1468      if ( match.hasMatch() )
 
 1470        const QStringList patternValues = match.captured( 1 ).split( 
' ' );
 
 1471        QVector< qreal > dashPattern;
 
 1473        for ( 
const QString &val : patternValues )
 
 1476          convertSize( val + match.captured( 2 ), length, patternUnits );
 
 1477          dashPattern.push_back( length * lineWidth * 2 );
 
 1480        simpleLine->setCustomDashVector( dashPattern );
 
 1481        simpleLine->setCustomDashPatternUnit( patternUnits );
 
 1482        simpleLine->setUseCustomDashPattern( 
true );
 
 1486    Qt::PenCapStyle capStyle = Qt::FlatCap;
 
 1487    Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
 
 1489    const QString 
id = lineStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1490    if ( 
id.contains( QLatin1String( 
"mapinfo-pen" ), Qt::CaseInsensitive ) )
 
 1495      capStyle = Qt::RoundCap;
 
 1496      joinStyle = Qt::RoundJoin;
 
 1500    const QString penCap = lineStyle.value( QStringLiteral( 
"cap" ) ).toString();
 
 1501    if ( penCap.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1503      capStyle = Qt::FlatCap;
 
 1505    else if ( penCap.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1507      capStyle = Qt::RoundCap;
 
 1509    else if ( penCap.compare( QLatin1String( 
"p" ), Qt::CaseInsensitive ) == 0 )
 
 1511      capStyle = Qt::SquareCap;
 
 1513    simpleLine->setPenCapStyle( capStyle );
 
 1516    const QString penJoin = lineStyle.value( QStringLiteral( 
"j" ) ).toString();
 
 1517    if ( penJoin.compare( QLatin1String( 
"m" ), Qt::CaseInsensitive ) == 0 )
 
 1519      joinStyle = Qt::MiterJoin;
 
 1521    else if ( penJoin.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1523      joinStyle = Qt::RoundJoin;
 
 1525    else if ( penJoin.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1527      joinStyle = Qt::BevelJoin;
 
 1529    simpleLine->setPenJoinStyle( joinStyle );
 
 1531    const QString priority = lineStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1532    if ( !priority.isEmpty() )
 
 1534      simpleLine->setRenderingPass( priority.toInt() );
 
 1536    return std::make_unique< QgsLineSymbol >( 
QgsSymbolLayerList() << simpleLine.release() );
 
 1539  auto convertBrush = [&convertColor]( 
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
 
 1541    const QColor foreColor = convertColor( brushStyle.value( QStringLiteral( 
"fc" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1542    const QColor backColor = convertColor( brushStyle.value( QStringLiteral( 
"bc" ), QString() ).toString() );
 
 1544    const QString 
id = brushStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1547    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-brush-(\\d+)" ) );
 
 1548    const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1549    if ( match.hasMatch() )
 
 1551      const int brushId = match.captured( 1 ).toInt();
 
 1558    const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-brush-(\\d+)" ) );
 
 1559    const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1561    Qt::BrushStyle style = Qt::SolidPattern;
 
 1562    if ( ogrMatch.hasMatch() )
 
 1564      const int brushId = ogrMatch.captured( 1 ).toInt();
 
 1568          style = Qt::SolidPattern;
 
 1572          style = Qt::NoBrush;
 
 1576          style = Qt::HorPattern;
 
 1580          style = Qt::VerPattern;
 
 1584          style = Qt::FDiagPattern;
 
 1588          style = Qt::BDiagPattern;
 
 1592          style = Qt::CrossPattern;
 
 1596          style = Qt::DiagCrossPattern;
 
 1602    if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
 
 1604      std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
 
 1605      backgroundFill->setLocked( 
true );
 
 1606      backgroundFill->setStrokeStyle( Qt::NoPen );
 
 1607      layers << backgroundFill.release();
 
 1610    std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
 
 1611    foregroundFill->setBrushStyle( style );
 
 1612    foregroundFill->setStrokeStyle( Qt::NoPen );
 
 1614    const QString priority = brushStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1615    if ( !priority.isEmpty() )
 
 1617      foregroundFill->setRenderingPass( priority.toInt() );
 
 1619    layers << foregroundFill.release();
 
 1620    return std::make_unique< QgsFillSymbol >( layers );
 
 1623  auto convertSymbol = [&convertColor, &convertSize, string]( 
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
 
 1625    const QColor color = convertColor( symbolStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1629    convertSize( symbolStyle.value( QStringLiteral( 
"s" ) ).toString(), symbolSize, symbolSizeUnit );
 
 1631    const double angle = symbolStyle.value( QStringLiteral( 
"a" ), QStringLiteral( 
"0" ) ).toDouble();
 
 1633    const QString 
id = symbolStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1636    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-sym-(\\d+)" ) );
 
 1637    const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1638    if ( match.hasMatch() )
 
 1640      const int symbolId = match.captured( 1 ).toInt();
 
 1651    std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
 
 1653    const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral( 
"font-sym-(\\d+)" ) );
 
 1654    const QRegularExpressionMatch fontMatch = sFontId.match( 
id );
 
 1655    if ( fontMatch.hasMatch() )
 
 1657      const int symId = fontMatch.captured( 1 ).toInt();
 
 1658      const QStringList families = symbolStyle.value( QStringLiteral( 
"f" ), QString() ).toString().split( 
',' );
 
 1660      bool familyFound = 
false;
 
 1663      for ( 
const QString &family : std::as_const( families ) )
 
 1671          fontFamily = processedFamily;
 
 1678        std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
 
 1679        fontMarker->setSizeUnit( symbolSizeUnit );
 
 1680        fontMarker->setAngle( -angle );
 
 1682        fontMarker->setColor( color );
 
 1684        const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1685        if ( strokeColor.isValid() )
 
 1687          fontMarker->setStrokeColor( strokeColor );
 
 1688          fontMarker->setStrokeWidth( 1 );
 
 1693          fontMarker->setStrokeWidth( 0 );
 
 1696        markerLayer = std::move( fontMarker );
 
 1698      else if ( !families.empty() )
 
 1707      const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-sym-(\\d+)" ) );
 
 1708      const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1711      bool isFilled = 
true;
 
 1712      if ( ogrMatch.hasMatch() )
 
 1714        const int symId = ogrMatch.captured( 1 ).toInt();
 
 1777      std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
 
 1778      simpleMarker->setSizeUnit( symbolSizeUnit );
 
 1779      simpleMarker->setStrokeWidth( 1.0 );
 
 1784        simpleMarker->setColor( color );
 
 1785        simpleMarker->setStrokeStyle( Qt::NoPen );
 
 1789        simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
 
 1790        simpleMarker->setStrokeColor( color );
 
 1793      const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1794      if ( strokeColor.isValid() )
 
 1796        simpleMarker->setStrokeColor( strokeColor );
 
 1797        simpleMarker->setStrokeStyle( Qt::SolidLine );
 
 1800      markerLayer = std::move( simpleMarker );
 
 1803    return std::make_unique< QgsMarkerSymbol >( 
QgsSymbolLayerList() << markerLayer.release() );
 
 1809      if ( styles.contains( QStringLiteral( 
"symbol" ) ) )
 
 1811        const QVariantMap symbolStyle = styles.value( QStringLiteral( 
"symbol" ) ).toMap();
 
 1812        return convertSymbol( symbolStyle );
 
 1820      if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1823        const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1824        return convertPen( lineStyle );
 
 1833      std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
 
 1834      if ( styles.contains( QStringLiteral( 
"brush" ) ) )
 
 1836        const QVariantMap brushStyle = styles.value( QStringLiteral( 
"brush" ) ).toMap();
 
 1837        fillSymbol = convertBrush( brushStyle );
 
 1841        std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
 
 1842        emptyFill->setBrushStyle( Qt::NoBrush );
 
 1843        fillSymbol = std::make_unique< QgsFillSymbol >( 
QgsSymbolLayerList() << emptyFill.release() );
 
 1846      std::unique_ptr< QgsSymbol > penSymbol;
 
 1847      if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1849        const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1850        penSymbol = convertPen( lineStyle );
 
 1855        const int count = penSymbol->symbolLayerCount();
 
 1865        for ( 
int i = 0; i < count; ++i )
 
 1867          std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
 
 1868          layer->setLocked( 
true );
 
 1869          fillSymbol->appendSymbolLayer( layer.release() );
 
 
 1885  variantType = QMetaType::Type::UnknownType;
 
 1886  variantSubType = QMetaType::Type::UnknownType;
 
 1891      if ( ogrSubType == OFSTBoolean )
 
 1893        variantType = QMetaType::Type::Bool;
 
 1894        ogrSubType = OFSTBoolean;
 
 1897        variantType = QMetaType::Type::Int;
 
 1900      variantType = QMetaType::Type::LongLong;
 
 1903      variantType = QMetaType::Type::Double;
 
 1906      variantType = QMetaType::Type::QDate;
 
 1909      variantType = QMetaType::Type::QTime;
 
 1912      variantType = QMetaType::Type::QDateTime;
 
 1916      variantType = QMetaType::Type::QByteArray;
 
 1921      if ( ogrSubType == OFSTJSON )
 
 1923        ogrSubType = OFSTJSON;
 
 1924        variantType = QMetaType::Type::QVariantMap;
 
 1925        variantSubType = QMetaType::Type::QString;
 
 1929        variantType = QMetaType::Type::QString;
 
 1934    case OFTWideStringList:
 
 1935      variantType = QMetaType::Type::QStringList;
 
 1936      variantSubType = QMetaType::Type::QString;
 
 1939    case OFTIntegerList:
 
 1940      variantType = QMetaType::Type::QVariantList;
 
 1941      variantSubType = QMetaType::Type::Int;
 
 1945      variantType = QMetaType::Type::QVariantList;
 
 1946      variantSubType = QMetaType::Type::Double;
 
 1949    case OFTInteger64List:
 
 1950      variantType = QMetaType::Type::QVariantList;
 
 1951      variantSubType = QMetaType::Type::LongLong;
 
 
 1958  ogrSubType = OFSTNone;
 
 1959  switch ( variantType )
 
 1961    case QMetaType::Type::Bool:
 
 1962      ogrType = OFTInteger;
 
 1963      ogrSubType = OFSTBoolean;
 
 1966    case QMetaType::Type::Int:
 
 1967      ogrType = OFTInteger;
 
 1970    case QMetaType::Type::LongLong:
 
 1971      ogrType = OFTInteger64;
 
 1974    case QMetaType::Type::Double:
 
 1978    case QMetaType::Type::QChar:
 
 1979    case QMetaType::Type::QString:
 
 1980      ogrType = OFTString;
 
 1983    case QMetaType::Type::QStringList:
 
 1984      ogrType = OFTStringList;
 
 1987    case QMetaType::Type::QByteArray:
 
 1988      ogrType = OFTBinary;
 
 1991    case QMetaType::Type::QDate:
 
 1995    case QMetaType::Type::QTime:
 
 1998    case QMetaType::Type::QDateTime:
 
 1999      ogrType = OFTDateTime;
 
 2003      ogrType = OFTString;
 
 
 2010  if ( 
string.isEmpty() )
 
 2018      res = 
string.toInt( &ok );
 
 2022      res = 
string.toLongLong( &ok );
 
 2026      res = 
string.toDouble( &ok );
 
 2036      res = QDate::fromString( 
string, Qt::ISODate );
 
 2041      res = QTime::fromString( 
string, Qt::ISODate );
 
 2046      res = QDateTime::fromString( 
string, Qt::ISODate );
 
 2056  return ok ? res : QVariant();
 
 
 2064  const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
 
 2066  int nMaxIntLen = 11;
 
 2067  int nMaxInt64Len = 21;
 
 2068  int nMaxDoubleLen = 20;
 
 2069  int nMaxDoublePrec = 15;
 
 2071  if ( driverName == QLatin1String( 
"GPKG" ) )
 
 2081  QList<QgsVectorDataProvider::NativeType> nativeTypes;
 
 2085      << 
QgsVectorDataProvider::NativeType( QObject::tr( 
"Decimal number (real)" ), QStringLiteral( 
"double" ), QMetaType::Type::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
 
 2088  if ( driverName == QLatin1String( 
"GPKG" ) )
 
 2089    nativeTypes << 
QgsVectorDataProvider::NativeType( QObject::tr( 
"JSON (string)" ), QStringLiteral( 
"JSON" ), QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
 
 2091  bool supportsDate = 
true;
 
 2092  bool supportsTime = 
true;
 
 2093  bool supportsDateTime = 
true;
 
 2094  bool supportsBinary = 
false;
 
 2095  bool supportIntegerList = 
false;
 
 2096  bool supportInteger64List = 
false;
 
 2097  bool supportRealList = 
false;
 
 2098  bool supportsStringList = 
false;
 
 2102  if ( 
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr ) )
 
 2104    char **papszTokens = CSLTokenizeString2( pszDataTypes, 
" ", 0 );
 
 2105    supportsDate = CSLFindString( papszTokens, 
"Date" ) >= 0;
 
 2106    supportsTime = CSLFindString( papszTokens, 
"Time" ) >= 0;
 
 2107    supportsDateTime = CSLFindString( papszTokens, 
"DateTime" ) >= 0;
 
 2108    supportsBinary = CSLFindString( papszTokens, 
"Binary" ) >= 0;
 
 2109    supportIntegerList = CSLFindString( papszTokens, 
"IntegerList" ) >= 0;
 
 2110    supportInteger64List = CSLFindString( papszTokens, 
"Integer64List" ) >= 0;
 
 2111    supportRealList = CSLFindString( papszTokens, 
"RealList" ) >= 0;
 
 2112    supportsStringList = CSLFindString( papszTokens, 
"StringList" ) >= 0;
 
 2113    CSLDestroy( papszTokens );
 
 2118#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0) 
 2119  if ( driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 2121    supportsDateTime = 
false;
 
 2135  if ( supportsDateTime )
 
 2140  if ( supportsBinary )
 
 2145  if ( supportIntegerList )
 
 2150  if ( supportInteger64List )
 
 2155  if ( supportRealList )
 
 2160  if ( supportsStringList )
 
 2166  const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES, 
nullptr );
 
 2167  if ( pszDataSubTypes && strstr( pszDataSubTypes, 
"Boolean" ) )
 
 
 2178#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0) 
 2184  const QString name{ OGR_FldDomain_GetName( domain ) };
 
 2185  const QString description{ OGR_FldDomain_GetDescription( domain ) };
 
 2187  QMetaType::Type fieldType = QMetaType::Type::UnknownType;
 
 2188  QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
 
 2189  const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
 
 2190  const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
 
 2191  ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
 
 2193  std::unique_ptr< QgsFieldDomain > res;
 
 2194  switch ( OGR_FldDomain_GetDomainType( domain ) )
 
 2198      QList< QgsCodedValue > values;
 
 2199      const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
 
 2200      while ( codedValue && codedValue->pszCode )
 
 2202        const QString code( codedValue->pszCode );
 
 2207        const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
 
 2208        values.append( 
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
 
 2213      res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
 
 2220      bool minIsInclusive = 
false;
 
 2221      if ( 
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
 
 2226      bool maxIsInclusive = 
false;
 
 2227      if ( 
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
 
 2232      res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
 
 2233            minValue, minIsInclusive,
 
 2234            maxValue, maxIsInclusive );
 
 2239      res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
 
 2240            QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
 
 2244  switch ( OGR_FldDomain_GetMergePolicy( domain ) )
 
 2246    case OFDMP_DEFAULT_VALUE:
 
 2252    case OFDMP_GEOMETRY_WEIGHTED:
 
 2257  switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
 
 2259    case OFDSP_DEFAULT_VALUE:
 
 2262    case OFDSP_DUPLICATE:
 
 2265    case OFDSP_GEOMETRY_RATIO:
 
 
 2277  OGRFieldType domainFieldType = OFTInteger;
 
 2278  OGRFieldSubType domainFieldSubType = OFSTNone;
 
 2279  variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
 
 2281  OGRFieldDomainH res = 
nullptr;
 
 2282  switch ( domain->
type() )
 
 2286      std::vector< OGRCodedValue > enumeration;
 
 2287      const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
 
 2288      enumeration.reserve( values.size() );
 
 2291        OGRCodedValue codedValue;
 
 2292        codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
 
 2293        codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
 
 2294        enumeration.push_back( codedValue );
 
 2297      last.pszCode = 
nullptr;
 
 2298      last.pszValue = 
nullptr;
 
 2299      enumeration.push_back( last );
 
 2300      res = OGR_CodedFldDomain_Create(
 
 2301              domain->
name().toUtf8().constData(),
 
 2308      for ( 
const OGRCodedValue &value : std::as_const( enumeration ) )
 
 2310        CPLFree( value.pszCode );
 
 2311        CPLFree( value.pszValue );
 
 2318      std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
 
 2319      std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
 
 2322      res = OGR_RangeFldDomain_Create(
 
 2323              domain->
name().toUtf8().constData(),
 
 2328              qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
 
 2330              qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
 
 2337      res = OGR_GlobFldDomain_Create(
 
 2338              domain->
name().toUtf8().constData(),
 
 2342              qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
 
 2351      OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
 
 2354      OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
 
 2357      OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
 
 2364      OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
 
 2367      OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
 
 2370      OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
 
 
 2383#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
 2387  const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
 
 2389  const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
 
 2391  QVariantMap leftTableUriParts = datasetUriParts;
 
 2392  leftTableUriParts.insert( QStringLiteral( 
"layerName" ), leftTableName );
 
 2393  const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
 
 2395  const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
 
 2396  QVariantMap rightTableUriParts = datasetUriParts;
 
 2397  rightTableUriParts.insert( QStringLiteral( 
"layerName" ), rightTableName );
 
 2398  const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
 
 2400  const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
 
 2401  QString mappingTableSource;
 
 2402  if ( !mappingTableName.isEmpty() )
 
 2404    QVariantMap mappingTableUriParts = datasetUriParts;
 
 2405    mappingTableUriParts.insert( QStringLiteral( 
"layerName" ), mappingTableName );
 
 2406    mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
 
 2409  const QString relationshipName( GDALRelationshipGetName( relationship ) );
 
 2411  char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
 
 2413  CSLDestroy( cslLeftTableFieldNames );
 
 2415  char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
 
 2417  CSLDestroy( cslRightTableFieldNames );
 
 2419  char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
 
 2421  CSLDestroy( cslLeftMappingTableFieldNames );
 
 2423  char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
 
 2425  CSLDestroy( cslRightMappingTableFieldNames );
 
 2427  const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
 
 2428  const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
 
 2429  const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
 
 2431  const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
 
 2433  switch ( relationshipType )
 
 2439    case GRT_ASSOCIATION:
 
 2443    case GRT_AGGREGATION:
 
 2444      QgsLogger::warning( 
"Aggregation relationships are not supported, treating as association instead" );
 
 2448  const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
 
 2450  switch ( eCardinality )
 
 2452    case GRC_ONE_TO_ONE:
 
 2455    case GRC_ONE_TO_MANY:
 
 2458    case GRC_MANY_TO_ONE:
 
 2461    case GRC_MANY_TO_MANY:
 
 2466  switch ( cardinality )
 
 2475                           QString(), QString(), rightTableSource, QStringLiteral( 
"ogr" ),
 
 2476                           QString(), QString(), leftTableSource, QStringLiteral( 
"ogr" ) );
 
 2491                           QString(), QString(), rightTableSource, QStringLiteral( 
"ogr" ),
 
 2492                           QString(), QString(), leftTableSource, QStringLiteral( 
"ogr" ) );
 
 
 2510  GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
 
 2514      gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
 
 2517      gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
 
 2520      gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
 
 2523      gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
 
 2530  const QString leftTableName = leftParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2531  if ( leftTableName.isEmpty() )
 
 2533    error = QObject::tr( 
"Parent table name was not set" );
 
 2538  const QString rightTableName = rightParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2539  if ( rightTableName.isEmpty() )
 
 2541    error = QObject::tr( 
"Child table name was not set" );
 
 2545  if ( leftParts.value( QStringLiteral( 
"path" ) ).toString() != rightParts.value( QStringLiteral( 
"path" ) ).toString() )
 
 2547    error = QObject::tr( 
"Parent and child table must be from the same dataset" );
 
 2551  QString mappingTableName;
 
 2555    mappingTableName = mappingParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2556    if ( leftParts.value( QStringLiteral( 
"path" ) ).toString() != mappingParts.value( QStringLiteral( 
"path" ) ).toString() )
 
 2558      error = QObject::tr( 
"Parent and mapping table must be from the same dataset" );
 
 2564      leftTableName.toLocal8Bit().constData(),
 
 2565      rightTableName.toLocal8Bit().constData(),
 
 2570  int count = leftFieldNames.count();
 
 2571  char **lst = 
new char *[count + 1];
 
 2575    for ( 
const QString &
string : leftFieldNames )
 
 2577      lst[pos] = CPLStrdup( 
string.toLocal8Bit().constData() );
 
 2581  lst[count] = 
nullptr;
 
 2582  GDALRelationshipSetLeftTableFields( relationH.get(), lst );
 
 2587  count = rightFieldNames.count();
 
 2588  lst = 
new char *[count + 1];
 
 2592    for ( 
const QString &
string : rightFieldNames )
 
 2594      lst[pos] = CPLStrdup( 
string.toLocal8Bit().constData() );
 
 2598  lst[count] = 
nullptr;
 
 2599  GDALRelationshipSetRightTableFields( relationH.get(), lst );
 
 2602  if ( !mappingTableName.isEmpty() )
 
 2604    GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
 
 2608    int count = leftFieldNames.count();
 
 2609    char **lst = 
new char *[count + 1];
 
 2613      for ( 
const QString &
string : leftFieldNames )
 
 2615        lst[pos] = CPLStrdup( 
string.toLocal8Bit().constData() );
 
 2619    lst[count] = 
nullptr;
 
 2620    GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
 
 2625    count = rightFieldNames.count();
 
 2626    lst = 
new char *[count + 1];
 
 2630      for ( 
const QString &
string : rightFieldNames )
 
 2632        lst[pos] = CPLStrdup( 
string.toLocal8Bit().constData() );
 
 2636    lst[count] = 
nullptr;
 
 2637    GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
 
 2645      GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
 
 2649      GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
 
 2655    GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
 
 2657    GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
 
 2661    GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
 
 
 2669  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2673    errCause = QObject::tr( 
"No styles available on DB" );
 
 2677  if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
 
 2680    errCause = QObject::tr( 
"No styles available on DB" );
 
 2684  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2686  OGR_L_ResetReading( hLayer );
 
 2688  QList<qlonglong> listTimestamp;
 
 2689  QMap<int, QString> mapIdToStyleName;
 
 2690  QMap<int, QString> mapIdToDescription;
 
 2691  QMap<qlonglong, QList<int> > mapTimestampToId;
 
 2692  int numberOfRelatedStyles = 0;
 
 2700    QString tableName( QString::fromUtf8(
 
 2701                         OGR_F_GetFieldAsString( hFeature.get(),
 
 2702                             OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_name" ) ) ) );
 
 2703    QString geometryColumn( QString::fromUtf8(
 
 2704                              OGR_F_GetFieldAsString( hFeature.get(),
 
 2705                                  OGR_FD_GetFieldIndex( hLayerDefn, 
"f_geometry_column" ) ) ) );
 
 2706    QString styleName( QString::fromUtf8(
 
 2707                         OGR_F_GetFieldAsString( hFeature.get(),
 
 2708                             OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) ) );
 
 2709    QString description( QString::fromUtf8(
 
 2710                           OGR_F_GetFieldAsString( hFeature.get(),
 
 2711                               OGR_FD_GetFieldIndex( hLayerDefn, 
"description" ) ) ) );
 
 2712    int fid = 
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
 
 2713    if ( tableName == layerName &&
 
 2714         geometryColumn == geomColumn )
 
 2717      QString id( QString::number( fid ) );
 
 2719      names.append( styleName );
 
 2720      descriptions.append( description );
 
 2721      ++ numberOfRelatedStyles;
 
 2725      int  year, month, day, hour, minute, second, TZ;
 
 2726      OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"update_time" ),
 
 2727                                &year, &month, &day, &hour, &minute, &second, &TZ );
 
 2728      const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
 
 2729                           static_cast<qlonglong
>( month ) * 31 * 24 * 3600 + 
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
 
 2731      listTimestamp.append( ts );
 
 2732      mapIdToStyleName[fid] = styleName;
 
 2733      mapIdToDescription[fid] = description;
 
 2734      mapTimestampToId[ts].append( fid );
 
 2738  std::sort( listTimestamp.begin(), listTimestamp.end() );
 
 2740  for ( 
int i = listTimestamp.size() - 1; i >= 0; i-- )
 
 2742    const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
 
 2743    for ( 
int j = 0; j < listId.size(); j++ )
 
 2745      int fid = listId[j];
 
 2746      QString id( QString::number( fid ) );
 
 2748      names.append( mapIdToStyleName[fid] );
 
 2749      descriptions.append( mapIdToDescription[fid] );
 
 2753  return numberOfRelatedStyles;
 
 
 2761  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2765  const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
 
 2767  const QString checkQuery = QStringLiteral( 
"f_table_schema=''" 
 2768                             " AND f_table_name=%1" 
 2769                             " AND f_geometry_column=%2" 
 2770                             " AND styleName=%3" )
 
 2771                             .arg( QgsOgrProviderUtils::quotedValue( layerName ),
 
 2772                                   QgsOgrProviderUtils::quotedValue( geomColumn ),
 
 2773                                   QgsOgrProviderUtils::quotedValue( realStyleId ) );
 
 2774  OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
 
 2775  OGR_L_ResetReading( hLayer );
 
 2777  OGR_L_ResetReading( hLayer );
 
 
 2787  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2791    errCause = QObject::tr( 
"No styles available on DB" );
 
 2796  int id = styleId.toInt( &ok );
 
 2799    errCause = QObject::tr( 
"Invalid style identifier" );
 
 2806    errCause = QObject::tr( 
"No style corresponding to style identifier" );
 
 2810  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2811  QString styleQML( QString::fromUtf8(
 
 2812                      OGR_F_GetFieldAsString( hFeature.get(),
 
 2813                          OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) ) );
 
 2814  OGR_L_ResetReading( hLayer );
 
 
 2823  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2828    errCause = QObject::tr( 
"Connection to database failed" );
 
 2833    if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
 
 2835      errCause = QObject::tr( 
"Error executing the delete query." );
 
 
 2848  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2852    errCause = QObject::tr( 
"No styles available on DB" );
 
 2856  QString selectQmlQuery = QStringLiteral( 
"f_table_schema=''" 
 2857                           " AND f_table_name=%1" 
 2858                           " AND f_geometry_column=%2" 
 2859                           " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END" 
 2860                           ",update_time DESC" )
 
 2861                           .arg( QgsOgrProviderUtils::quotedValue( layerName ),
 
 2862                                 QgsOgrProviderUtils::quotedValue( geomColumn ) );
 
 2863  OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
 
 2864  OGR_L_ResetReading( hLayer );
 
 2865  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2867  qlonglong moreRecentTimestamp = 0;
 
 2873    if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ) ) )
 
 2875      styleQML = QString::fromUtf8(
 
 2876                   OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) );
 
 2877      styleName = QString::fromUtf8(
 
 2878                    OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) );
 
 2882    int  year, month, day, hour, minute, second, TZ;
 
 2883    OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"update_time" ),
 
 2884                              &year, &month, &day, &hour, &minute, &second, &TZ );
 
 2885    qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
 
 2886                   static_cast<qlonglong
>( month ) * 31 * 24 * 3600 + 
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
 
 2887    if ( ts > moreRecentTimestamp )
 
 2889      moreRecentTimestamp = ts;
 
 2890      styleQML = QString::fromUtf8(
 
 2891                   OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) );
 
 2892      styleName = QString::fromUtf8(
 
 2893                    OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) );
 
 2896  OGR_L_ResetReading( hLayer );
 
 
 2902  GDALDatasetH hDS, 
const QString &layerName, 
const QString &geomColumn, 
const QString &qmlStyle, 
const QString &sldStyle,
 
 2903  const QString &styleName, 
const QString &styleDescription,
 
 2904  const QString &uiFileContent, 
bool useAsDefault, QString &errCause
 
 2908  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2915    char **options = 
nullptr;
 
 2917    options = CSLSetNameValue( options, 
"FID", 
"id" );
 
 2918    hLayer = GDALDatasetCreateLayer( hDS, 
"layer_styles", 
nullptr, wkbNone, options );
 
 2919    QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
 
 2920    CSLDestroy( options );
 
 2923      errCause = QObject::tr( 
"Unable to save layer style. It's not possible to create the destination table on the database." );
 
 2929      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2930      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2934      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2935      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2939      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2940      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2944      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2945      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2949      OGR_Fld_SetWidth( fld.get(), 30 );
 
 2950      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2954      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2958      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2962      OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
 
 2963      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2967      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2971      OGR_Fld_SetWidth( fld.get(), 30 );
 
 2972      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2976      OGR_Fld_SetWidth( fld.get(), 30 );
 
 2977      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2981      OGR_Fld_SetDefault( fld.get(), 
"CURRENT_TIMESTAMP" );
 
 2982      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2986      errCause = QObject::tr( 
"Unable to save layer style. It's not possible to create the destination table on the database." );
 
 2991  QString realStyleName =
 
 2992    styleName.isEmpty() ? layerName : styleName;
 
 2994  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2998    QString oldDefaultQuery = QStringLiteral( 
"useAsDefault = 1 AND f_table_schema=''" 
 2999                              " AND f_table_name=%1" 
 3000                              " AND f_geometry_column=%2" )
 
 3001                              .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
 
 3002                              .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
 
 3003    OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
 
 3007      OGR_F_SetFieldInteger( hFeature.get(),
 
 3008                             OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ),
 
 3010      bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
 
 3013        QgsDebugError( QStringLiteral( 
"Could not unset previous useAsDefault style" ) );
 
 3018  QString checkQuery = QStringLiteral( 
"f_table_schema=''" 
 3019                                       " AND f_table_name=%1" 
 3020                                       " AND f_geometry_column=%2" 
 3021                                       " AND styleName=%3" )
 
 3022                       .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
 
 3023                       .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
 
 3024                       .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
 
 3025  OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
 
 3026  OGR_L_ResetReading( hLayer );
 
 3028  OGR_L_ResetReading( hLayer );
 
 3037    hFeature.reset( OGR_F_Create( hLayerDefn ) );
 
 3038    OGR_F_SetFieldString( hFeature.get(),
 
 3039                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_catalog" ),
 
 3041    OGR_F_SetFieldString( hFeature.get(),
 
 3042                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_schema" ),
 
 3044    OGR_F_SetFieldString( hFeature.get(),
 
 3045                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_name" ),
 
 3046                          layerName.toUtf8().constData() );
 
 3047    OGR_F_SetFieldString( hFeature.get(),
 
 3048                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_geometry_column" ),
 
 3049                          geomColumn.toUtf8().constData() );
 
 3050    OGR_F_SetFieldString( hFeature.get(),
 
 3051                          OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ),
 
 3052                          realStyleName.toUtf8().constData() );
 
 3053    if ( !uiFileContent.isEmpty() )
 
 3055      OGR_F_SetFieldString( hFeature.get(),
 
 3056                            OGR_FD_GetFieldIndex( hLayerDefn, 
"ui" ),
 
 3057                            uiFileContent.toUtf8().constData() );
 
 3060  OGR_F_SetFieldString( hFeature.get(),
 
 3061                        OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ),
 
 3062                        qmlStyle.toUtf8().constData() );
 
 3063  OGR_F_SetFieldString( hFeature.get(),
 
 3064                        OGR_FD_GetFieldIndex( hLayerDefn, 
"styleSLD" ),
 
 3065                        sldStyle.toUtf8().constData() );
 
 3066  OGR_F_SetFieldInteger( hFeature.get(),
 
 3067                         OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ),
 
 3068                         useAsDefault ? 1 : 0 );
 
 3069  OGR_F_SetFieldString( hFeature.get(),
 
 3070                        OGR_FD_GetFieldIndex( hLayerDefn, 
"description" ),
 
 3071                        ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
 
 3072  OGR_F_SetFieldString( hFeature.get(),
 
 3073                        OGR_FD_GetFieldIndex( hLayerDefn, 
"owner" ),
 
 3078    bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
 
 3080    bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
 
 3085    errCause = QObject::tr( 
"Error looking for style. The query was logged" );
 
 
RelationshipStrength
Relationship strength.
 
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
 
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
 
@ GeometryWeighted
New values are computed as the weighted average of the source values.
 
@ DefaultValue
Use default field value.
 
@ GeometryRatio
New values are computed by the ratio of their area/length compared to the area/length of the original...
 
@ UnsetField
Clears the field value so that the data provider backend will populate using any backend triggers or ...
 
@ DefaultValue
Use default field value.
 
@ Duplicate
Duplicate original value.
 
MarkerShape
Marker shapes.
 
@ Cross2
Rotated cross (lines only), 'x' shape.
 
@ Cross
Cross (lines only)
 
RenderUnit
Rendering size units.
 
@ Millimeters
Millimeters.
 
@ Points
Points (e.g., for font sizes)
 
@ Coded
Coded field domain.
 
@ Range
Numeric range field domain (min/max)
 
@ Glob
Glob string pattern field domain.
 
RelationshipCardinality
Relationship cardinality.
 
@ ManyToMany
Many to many relationship.
 
@ ManyToOne
Many to one relationship.
 
@ OneToOne
One to one relationship.
 
@ OneToMany
One to many relationship.
 
WkbType
The WKB type describes the number of dimensions a geometry has.
 
@ LineString25D
LineString25D.
 
@ MultiSurfaceM
MultiSurfaceM.
 
@ MultiLineStringZM
MultiLineStringZM.
 
@ MultiPointZM
MultiPointZM.
 
@ MultiPointZ
MultiPointZ.
 
@ CompoundCurve
CompoundCurve.
 
@ MultiPolygonZM
MultiPolygonZM.
 
@ LineStringM
LineStringM.
 
@ MultiLineStringM
MultiLineStringM.
 
@ MultiPointM
MultiPointM.
 
@ LineStringZM
LineStringZM.
 
@ GeometryCollectionZM
GeometryCollectionZM.
 
@ CompoundCurveZM
CompoundCurveZM.
 
@ CompoundCurveM
CompoundCurveM.
 
@ MultiPolygon
MultiPolygon.
 
@ GeometryCollectionZ
GeometryCollectionZ.
 
@ GeometryCollectionM
GeometryCollectionM.
 
@ CircularStringZM
CircularStringZM.
 
@ MultiSurfaceZ
MultiSurfaceZ.
 
@ CurvePolygonZM
CurvePolygonZM.
 
@ MultiLineString
MultiLineString.
 
@ MultiPolygonM
MultiPolygonM.
 
@ MultiCurveZM
MultiCurveZM.
 
@ MultiSurfaceZM
MultiSurfaceZM.
 
@ CurvePolygonM
CurvePolygonM.
 
@ CircularString
CircularString.
 
@ MultiLineStringZ
MultiLineStringZ.
 
@ GeometryCollection
GeometryCollection.
 
@ MultiPolygonZ
MultiPolygonZ.
 
@ CurvePolygonZ
CurvePolygonZ.
 
@ CompoundCurveZ
CompoundCurveZ.
 
@ MultiCurveZ
MultiCurveZ.
 
@ MultiCurveM
MultiCurveM.
 
@ CircularStringM
CircularStringM.
 
@ CurvePolygon
CurvePolygon.
 
@ CircularStringZ
CircularStringZ.
 
@ LineStringZ
LineStringZ.
 
@ MultiSurface
MultiSurface.
 
@ PreferredGdal
Preferred format for conversion of CRS to WKT for use with the GDAL library.
 
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
 
static endian_t endian()
Returns whether this machine uses big or little endian.
 
Associates a code and a value.
 
This class represents a coordinate reference system (CRS).
 
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
 
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
 
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
 
void setCoordinateEpoch(double epoch)
Sets the coordinate epoch, as a decimal year.
 
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
 
double coordinateEpoch() const
Returns the coordinate epoch, as a decimal year.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
 
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
 
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
 
void setId(QgsFeatureId id)
Sets the feature id for this feature.
 
void clearGeometry()
Removes any geometry associated with the feature.
 
void setValid(bool validity)
Sets the validity of the feature.
 
bool isValid() const
Returns the validity of this feature.
 
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
 
Base class for field domains.
 
Qgis::FieldDomainMergePolicy mergePolicy() const
Returns the merge policy.
 
Qgis::FieldDomainSplitPolicy splitPolicy() const
Returns the split policy.
 
QMetaType::Type fieldType() const
Returns the associated field type.
 
virtual Qgis::FieldDomainType type() const =0
Returns the type of field domain.
 
QString name() const
Returns the name of the field domain.
 
QString description() const
Returns the description of the field domain.
 
Encapsulate a field in an attribute table or data source.
 
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
 
Container of fields for a vector layer.
 
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
 
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
 
A geometry is the spatial representation of a feature.
 
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
 
static void warning(const QString &msg)
Goes to qWarning.
 
Context for a MapInfo symbol conversion operation.
 
static QgsFillSymbol * convertFillSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, const QColor &backColor=QColor())
Converts the MapInfo fill symbol with the specified identifier to a QgsFillSymbol.
 
static QgsMarkerSymbol * convertMarkerSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &color, double size, Qgis::RenderUnit sizeUnit)
Converts the MapInfo marker symbol with the specified identifier to a QgsMarkerSymbol.
 
static QgsLineSymbol * convertLineSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, double size, Qgis::RenderUnit sizeUnit, bool interleaved=false)
Converts the MapInfo line symbol with the specified identifier to a QgsLineSymbol.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
 
static QString readShapefileEncoding(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
 
static QgsWeakRelation convertRelationship(GDALRelationshipH relationship, const QString &datasetUri)
Converts an GDAL relationship definition to a QgsWeakRelation equivalent.
 
static QVariant stringToVariant(OGRFieldType type, OGRFieldSubType subType, const QString &string)
Converts a string to a variant, using the provider OGR field type and subType to determine the most a...
 
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
 
static QString loadStoredStyle(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, QString &styleName, QString &errCause)
Helper function for loading a stored styles in ogr/gdal database datasources.
 
static QString getStyleById(GDALDatasetH hDS, const QString &styleId, QString &errCause)
Helper function for getting a style by ID from ogr/gdal database datasources.
 
static Qgis::WkbType ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
 
static int listStyles(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Helper function for listing styles in ogr/gdal database datasources.
 
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
 
static QString OGRSpatialReferenceToWkt(OGRSpatialReferenceH srs)
Returns a WKT string corresponding to the specified OGR srs object.
 
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
 
static bool saveStyle(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Helper function for saving a style to ogr/gdal database datasources.
 
static bool styleExists(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, const QString &styleId, QString &errorCause)
Helper function for checking whether a style exists in ogr/gdal database datasources.
 
static QVariant OGRFieldtoVariant(const OGRField *value, OGRFieldType type)
Converts an OGRField value of the specified type into a QVariant.
 
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
 
static QStringList cStringListToQStringList(char **stringList)
Converts a c string list to a QStringList.
 
static void ogrFieldTypeToQVariantType(OGRFieldType ogrType, OGRFieldSubType ogrSubType, QMetaType::Type &variantType, QMetaType::Type &variantSubType)
Converts an OGR field type and sub type to the best matching QVariant::Type equivalent.
 
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
 
static QList< QgsVectorDataProvider::NativeType > nativeFieldTypesForDriver(GDALDriverH driver)
Returns the list of native field types supported for a driver.
 
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
 
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs(OGRSpatialReferenceH srs)
Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR srs object,...
 
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
 
static QString readShapefileEncodingFromCpg(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
 
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
 
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
 
static QString readShapefileEncodingFromLdid(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
 
static std::unique_ptr< QgsSymbol > symbolFromStyleString(const QString &string, Qgis::SymbolType type)
Creates a new QgsSymbol matching an OGR style string.
 
static std::unique_ptr< OGRField > variantToOGRField(const QVariant &value, OGRFieldType type)
Converts a QVariant to an OGRField value of specified type.
 
static bool deleteStyleById(GDALDatasetH hDS, const QString &styleId, QString &errCause)
Helper function for deleting a style by id from ogr/gdal database datasources.
 
static void variantTypeToOgrFieldType(QMetaType::Type variantType, OGRFieldType &ogrType, OGRFieldSubType &ogrSubType)
Converts an QVariant type to the best matching OGR field type and sub type.
 
static QVariantMap parseStyleString(const QString &string)
Parses an OGR style string to a variant map containing the style string components.
 
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
 
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
 
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
 
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
 
static bool shapeIsFilled(Qgis::MarkerShape shape)
Returns true if a symbol shape has a fill.
 
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
 
static QString typeToDisplayString(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
 
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
 
The QgsWeakRelation class represent a QgsRelation with possibly unresolved layers or unmatched fields...
 
void setMappingTable(const QgsVectorLayerRef &table)
Sets a weak reference to the mapping table, which forms the middle table in many-to-many relationship...
 
QStringList mappingReferencingLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
 
void setForwardPathLabel(const QString &label)
Sets the label of the forward path for the relationship.
 
QString mappingTableSource() const
Returns the source URI for the mapping table, which forms the middle table in many-to-many relationsh...
 
void setMappingReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
 
void setBackwardPathLabel(const QString &label)
Sets the label of the backward path for the relationship.
 
QString relatedTableType() const
Returns the type string of the related table.
 
void setReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the referencingLayer() involved in the relationship.
 
QString name() const
Returns the relationship's name.
 
QString backwardPathLabel() const
Returns the label of the backward path for the relationship.
 
void setMappingReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
 
QString referencedLayerSource() const
Returns the source URI for the referenced (or "parent" / "left") layer.
 
QString referencingLayerSource() const
Returns the source URI for the referencing (or "child" / "right") layer.
 
QString forwardPathLabel() const
Returns the label of the forward path for the relationship.
 
Qgis::RelationshipCardinality cardinality() const
Returns the relationship's cardinality.
 
void setCardinality(Qgis::RelationshipCardinality cardinality)
Sets the relationship's cardinality.
 
QStringList referencedLayerFields() const
Returns the list of fields from the referencedLayer() involved in the relationship.
 
QStringList mappingReferencedLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
 
void setRelatedTableType(const QString &type)
Sets the type string of the related table.
 
QStringList referencingLayerFields() const
Returns the list of fields from the referencingLayer() involved in the relationship.
 
void setReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the referencedLayer() involved in the relationship.
 
Qgis::RelationshipStrength strength() const
Returns the strength of the relation.
 
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
 
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
 
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
 
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
 
void CORE_EXPORT fast_delete_and_close(dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path)
Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying data store.
 
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
 
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
 
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.
 
std::unique_ptr< std::remove_pointer< GDALRelationshipH >::type, GDALRelationshipDeleter > relationship_unique_ptr
Scoped GDAL relationship.
 
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
 
void * OGRSpatialReferenceH
 
QList< QgsFeature > QgsFeatureList
 
#define DEFAULT_SIMPLELINE_WIDTH
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
#define DEFAULT_SIMPLEMARKER_SIZE
 
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
 
std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString(OGRGeometryH geom)
 
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
 
std::unique_ptr< QgsPolygon > ogrGeometryToQgsPolygon(OGRGeometryH geom)
 
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
 
std::unique_ptr< QgsMultiPolygon > ogrGeometryToQgsMultiPolygon(OGRGeometryH geom)
 
QList< QgsSymbolLayer * > QgsSymbolLayerList
 
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
 
const QgsCoordinateReferenceSystem & crs
 
void CORE_EXPORT operator()(GDALDatasetH datasource) const
Destroys an gdal dataset, using the correct gdal calls.
 
void CORE_EXPORT operator()(GDALRelationshipH relationship) const
Destroys GDAL relationship, using the correct gdal calls.
 
void CORE_EXPORT operator()(GDALWarpOptions *options) const
Destroys GDAL warp options, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRDataSourceH source) const
Destroys an OGR data source, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRFeatureH feature) const
Destroys an OGR feature, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRFieldDefnH definition) const
Destroys an OGR field definition, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRGeometryH geometry) const
Destroys an OGR geometry, using the correct gdal calls.