40#include "qgsogrproviderutils.h" 
   43#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
   54#include <QJsonDocument> 
   59#include <QRegularExpression> 
   61#include "ogr_srs_api.h" 
   63#include "nlohmann/json.hpp" 
   67  OGR_DS_Destroy( source );
 
 
   73  OGR_G_DestroyGeometry( geometry );
 
 
   78  OGR_Fld_Destroy( definition );
 
 
   83  OGR_F_Destroy( feature );
 
 
  100  CPLPushErrorHandler( CPLQuietErrorHandler );
 
  101  GDALDeleteDataset( driver, path.toUtf8().constData() );
 
  102  CPLPopErrorHandler();
 
 
  113  GDALDestroyWarpOptions( options );
 
 
  116#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
  119  GDALDestroyRelationship( relationship );
 
 
  123static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt, 
int nTZFlag )
 
  130  else if ( nTZFlag == 1 )
 
  132    dt.setTimeSpec( Qt::LocalTime );
 
  134  else if ( nTZFlag == 100 )
 
  136    dt.setTimeSpec( Qt::UTC );
 
  142    dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
 
  148  if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
 
  154      return value->Integer;
 
  157      return value->Integer64;
 
  164      return QString::fromUtf8( value->String );
 
  167      return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
 
  171      float secondsPart = 0;
 
  172      float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  173      return QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
 
  178      float secondsPart = 0;
 
  179      float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  180      QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
 
  181                                QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
 
  182      setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
 
  188      Q_ASSERT_X( 
false, 
"QgsOgrUtils::OGRFieldtoVariant", 
"OFTBinary type not supported" );
 
  194      res.reserve( value->IntegerList.nCount );
 
  195      for ( 
int i = 0; i < value->IntegerList.nCount; ++i )
 
  196        res << value->IntegerList.paList[ i ];
 
  200    case OFTInteger64List:
 
  203      res.reserve( value->Integer64List.nCount );
 
  204      for ( 
int i = 0; i < value->Integer64List.nCount; ++i )
 
  205        res << value->Integer64List.paList[ i ];
 
  212      res.reserve( value->RealList.nCount );
 
  213      for ( 
int i = 0; i < value->RealList.nCount; ++i )
 
  214        res << value->RealList.paList[ i ];
 
  219    case OFTWideStringList:
 
  222      res.reserve( value->StringList.nCount );
 
  223      for ( 
int i = 0; i < value->StringList.nCount; ++i )
 
  224        res << QString::fromUtf8( value->StringList.paList[ i ] );
 
 
  233  if ( datetime.timeSpec() == Qt::LocalTime )
 
  235  return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
 
 
  240  auto res = std::make_unique< OGRField >();
 
  242  switch ( value.userType() )
 
  244    case QMetaType::Type::UnknownType:
 
  245      OGR_RawField_SetUnset( res.get() );
 
  247    case QMetaType::Type::Bool:
 
  249      const int val = value.toBool() ? 1 : 0;
 
  250      if ( type == OFTInteger )
 
  252      else if ( type == OFTInteger64 )
 
  253        res->Integer64 = val;
 
  254      else if ( type == OFTReal )
 
  263    case QMetaType::Type::Int:
 
  265      const int val = value.toInt();
 
  266      if ( type == OFTInteger )
 
  268      else if ( type == OFTInteger64 )
 
  269        res->Integer64 = val;
 
  270      else if ( type == OFTReal )
 
  279    case QMetaType::Type::LongLong:
 
  281      const qint64 val = value.toLongLong();
 
  282      if ( type == OFTInteger )
 
  284        if ( val <= std::numeric_limits<int>::max() &&
 
  285             val >= std::numeric_limits<int>::min() )
 
  287          res->Integer = 
static_cast<int>( val );
 
  295      else if ( type == OFTInteger64 )
 
  296        res->Integer64 = val;
 
  297      else if ( type == OFTReal )
 
  299        res->Real = 
static_cast<double>( val );
 
  303        QgsDebugError( 
"Unsupported output data type for LongLong" );
 
  308    case QMetaType::Type::Double:
 
  310      double val = value.toDouble();
 
  311      if ( type == OFTInteger )
 
  313        if ( val <= std::numeric_limits<int>::max() &&
 
  314             val >= std::numeric_limits<int>::min() )
 
  316          res->Integer = 
static_cast<int>( val );
 
  324      else if ( type == OFTInteger64 )
 
  326        if ( val <= 
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
 
  327             val >= 
static_cast<double>( std::numeric_limits<qint64>::min() ) )
 
  329          res->Integer64 = 
static_cast<qint64
>( val );
 
  337      else if ( type == OFTReal )
 
  343        QgsDebugError( 
"Unsupported output data type for LongLong" );
 
  348    case QMetaType::Type::QChar:
 
  349    case QMetaType::Type::QString:
 
  351      if ( type == OFTString )
 
  352        res->String = CPLStrdup( value.toString().toUtf8().constData() );
 
  360    case QMetaType::Type::QDate:
 
  362      if ( type == OFTDate )
 
  364        const QDate date = value.toDate();
 
  365        res->Date.Day = date.day();
 
  366        res->Date.Month = date.month();
 
  367        res->Date.Year = 
static_cast<GInt16
>( date.year() );
 
  368        res->Date.TZFlag = 0;
 
  377    case QMetaType::Type::QTime:
 
  379      if ( type == OFTTime )
 
  381        const QTime time = value.toTime();
 
  382        res->Date.Hour = time.hour();
 
  383        res->Date.Minute = time.minute();
 
  384        res->Date.Second = 
static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 );
 
  385        res->Date.TZFlag = 0;
 
  394    case QMetaType::Type::QDateTime:
 
  396      if ( type == OFTDateTime )
 
  398        const QDateTime dt = value.toDateTime();
 
  399        const QDate date = dt.date();
 
  400        res->Date.Day = date.day();
 
  401        res->Date.Month = date.month();
 
  402        res->Date.Year = 
static_cast<GInt16
>( date.year() );
 
  403        const QTime time = dt.time();
 
  404        res->Date.Hour = time.hour();
 
  405        res->Date.Minute = time.minute();
 
  406        res->Date.Second = 
static_cast<float>( time.second() + 
static_cast< double >( time.msec() ) / 1000 );
 
  407        res->Date.TZFlag = OGRTZFlagFromQt( dt );
 
  411        QgsDebugError( 
"Unsupported output data type for DateTime" );
 
  418      QgsDebugError( 
"Unhandled variant type in variantToOGRField" );
 
  419      OGR_RawField_SetUnset( res.get() );
 
 
  435  feature.
setId( OGR_F_GetFID( ogrFet ) );
 
  438  if ( !readOgrFeatureGeometry( ogrFet, feature ) )
 
  443  if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
 
 
  458  int fieldCount = OGR_F_GetFieldCount( ogrFet );
 
  459  for ( 
int i = 0; i < fieldCount; ++i )
 
  461    OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
 
  468    QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
 
  469    QMetaType::Type varType;
 
  470    switch ( OGR_Fld_GetType( fldDef ) )
 
  473        if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
 
  474          varType = QMetaType::Type::Bool;
 
  476          varType = QMetaType::Type::Int;
 
  479        varType = QMetaType::Type::LongLong;
 
  482        varType = QMetaType::Type::Double;
 
  485        varType = QMetaType::Type::QDate;
 
  488        varType = QMetaType::Type::QTime;
 
  491        varType = QMetaType::Type::QDateTime;
 
  494        if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
 
  495          varType = QMetaType::Type::QVariantMap;
 
  497          varType = QMetaType::Type::QString;
 
  500        varType = QMetaType::Type::QString; 
 
 
  510  if ( attIndex < 0 || attIndex >= fields.
count() )
 
  518  return getOgrFeatureAttribute( ogrFet, field, attIndex, encoding, ok );
 
 
  523  if ( !ogrFet || attIndex < 0 )
 
  530  OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
 
  537    QgsDebugError( QStringLiteral( 
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
 
  547  auto getJsonValue = [&]() -> 
bool 
  549    const char *json = OGR_F_GetFieldAsString( ogrFet, attIndex );
 
  552      jsonContent = encoding->toUnicode( json ).toUtf8();
 
  554      jsonContent = QString::fromUtf8( json ).toUtf8();
 
  558      const nlohmann::json json_element = json::parse( jsonContent.toStdString() );
 
  562    catch ( 
const json::parse_error &e )
 
  564      QgsDebugMsgLevel( QStringLiteral( 
"Error parsing JSON: %1" ).arg( e.what() ), 2 );
 
  569  if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
 
  571    switch ( field.
type() )
 
  573      case QMetaType::Type::QString:
 
  575        if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  578            value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  580            value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  585          if ( value.isNull() )
 
  586            value = QVariant( QStringLiteral( 
"" ) ); 
 
  591      case QMetaType::Type::Int:
 
  592        value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
 
  594      case QMetaType::Type::Bool:
 
  595        value = QVariant( 
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
 
  597      case QMetaType::Type::LongLong:
 
  598        value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
 
  600      case QMetaType::Type::Double:
 
  601        value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
 
  603      case QMetaType::Type::QDate:
 
  604      case QMetaType::Type::QDateTime:
 
  605      case QMetaType::Type::QTime:
 
  607        int year, month, day, hour, minute, tzf;
 
  609        float secondsPart = 0;
 
  611        OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
 
  612        float millisecondPart = std::modf( second, &secondsPart );
 
  614        if ( field.
type() == QMetaType::Type::QDate )
 
  615          value = QDate( year, month, day );
 
  616        else if ( field.
type() == QMetaType::Type::QTime )
 
  617          value = QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
 
  620          QDateTime dt = QDateTime( QDate( year, month, day ),
 
  621                                    QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
 
  622          setQTTimeZoneFromOGRTZFlag( dt, tzf );
 
  628      case QMetaType::Type::QByteArray:
 
  631        const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
 
  635        QByteArray ba = QByteArray::fromRawData( 
reinterpret_cast<const char *
>( b ), size );
 
  642      case QMetaType::Type::QStringList:
 
  644        if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  647          char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  648          const int count = CSLCount( lst );
 
  651            list.reserve( count );
 
  652            for ( 
int i = 0; i < count; i++ )
 
  655                list << encoding->toUnicode( lst[i] );
 
  657                list << QString::fromUtf8( lst[i] );
 
  665      case QMetaType::Type::QVariantList:
 
  669          case QMetaType::Type::QString:
 
  671            if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  674              char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  675              const int count = CSLCount( lst );
 
  678                list.reserve( count );
 
  679                for ( 
int i = 0; i < count; i++ )
 
  682                    list << encoding->toUnicode( lst[i] );
 
  684                    list << QString::fromUtf8( lst[i] );
 
  692          case QMetaType::Type::Int:
 
  694            if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  698              const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
 
  701                list.reserve( count );
 
  702                for ( 
int i = 0; i < count; i++ )
 
  712          case QMetaType::Type::Double:
 
  714            if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  718              const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
 
  721                list.reserve( count );
 
  722                for ( 
int i = 0; i < count; i++ )
 
  732          case QMetaType::Type::LongLong:
 
  734            if ( field.
typeName() != QStringLiteral( 
"JSON" ) || ! getJsonValue() )
 
  738              const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
 
  741                list.reserve( count );
 
  742                for ( 
int i = 0; i < count; i++ )
 
  754            Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
  763      case QMetaType::Type::QVariantMap:
 
  768          value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  770          value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  774        Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
 
  797  for ( 
int idx = 0; idx < fields.
count(); ++idx )
 
  799    QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
 
 
  813  OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
 
  817    feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
 
 
  827  OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
 
  828  return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
 
 
  833  auto mp = std::make_unique< QgsMultiPoint >();
 
  835  const int count = OGR_G_GetGeometryCount( geom );
 
  836  mp->reserve( count );
 
  837  for ( 
int i = 0; i < count; ++i )
 
 
  849  int count = OGR_G_GetPointCount( geom );
 
  850  QVector< double > x( count );
 
  851  QVector< double > y( count );
 
  853  double *pz = 
nullptr;
 
  859  double *pm = 
nullptr;
 
  866  OGR_G_GetPointsZM( geom, x.data(), 
sizeof( 
double ), y.data(), 
sizeof( 
double ), pz, 
sizeof( 
double ), pm, 
sizeof( 
double ) );
 
 
  873  auto mp = std::make_unique< QgsMultiLineString >();
 
  875  const int count = OGR_G_GetGeometryCount( geom );
 
  876  mp->reserve( count );
 
  877  for ( 
int i = 0; i < count; ++i )
 
 
  887  auto polygon = std::make_unique< QgsPolygon >();
 
  889  const int count = OGR_G_GetGeometryCount( geom );
 
  895  for ( 
int i = 1; i < count; ++i )
 
 
  905  auto polygon = std::make_unique< QgsMultiPolygon >();
 
  907  const int count = OGR_G_GetGeometryCount( geom );
 
  908  polygon->reserve( count );
 
  909  for ( 
int i = 0; i < count; ++i )
 
 
  919  switch ( ogrGeomType )
 
 
 1008  const auto ogrGeomType = OGR_G_GetGeometryType( geom );
 
 1009  Qgis::WkbType wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
 
 1051  if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
 
 1054    if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
 
 1055         wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
 
 1057      auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
 
 1058      auto ret = ogrGeometryToQgsGeometry( newGeom );
 
 1059      OGR_G_DestroyGeometry( newGeom );
 
 1065  int memorySize = OGR_G_WkbSize( geom );
 
 1066  unsigned char *wkb = 
new unsigned char[memorySize];
 
 
 1077  if ( 
string.isEmpty() )
 
 1080  QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
 1083  QByteArray ba = 
string.toUtf8();
 
 1084  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
 1085                                    static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
 1090    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1094  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 1098    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1103  while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
 1105    QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
 
 1111  VSIUnlink( randomFileName.toUtf8().constData() );
 
 
 1119  if ( 
string.isEmpty() )
 
 1122  QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
 1125  QByteArray ba = 
string.toUtf8();
 
 1126  VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
 1127                                    static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
 1132    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1136  OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
 1140    VSIUnlink( randomFileName.toUtf8().constData() );
 
 1146  if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
 1148    fields = readOgrFields( oFeat.get(), encoding );
 
 1152  VSIUnlink( randomFileName.toUtf8().constData() );
 
 
 1161  QStringList strings;
 
 1163  for ( 
qgssize i = 0; stringList[i]; ++i )
 
 1165    strings.
append( QString::fromUtf8( stringList[i] ) );
 
 
 1176  char *pszWkt = 
nullptr;
 
 1177  const QByteArray multiLineOption = QStringLiteral( 
"MULTILINE=NO" ).toLocal8Bit();
 
 1178  const QByteArray formatOption = QStringLiteral( 
"FORMAT=WKT2" ).toLocal8Bit();
 
 1179  const char *
const options[] = {multiLineOption.constData(), formatOption.constData(), 
nullptr};
 
 1180  OSRExportToWktEx( srs, &pszWkt, options );
 
 1182  const QString res( pszWkt );
 
 
 1189  const QString wkt = OGRSpatialReferenceToWkt( srs );
 
 1190  if ( wkt.isEmpty() )
 
 1193  const char *authorityName = OSRGetAuthorityName( srs, 
nullptr );
 
 1194  const char *authorityCode = OSRGetAuthorityCode( srs, 
nullptr );
 
 1196  if ( authorityName && authorityCode )
 
 1198    QString authId = QString( authorityName ) + 
':' + QString( authorityCode );
 
 1199    OGRSpatialReferenceH ogrSrsTmp = OSRNewSpatialReference( 
nullptr );
 
 1201    if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
 
 1202         OSRIsSame( srs, ogrSrsTmp ) )
 
 1207    OSRDestroySpatialReference( ogrSrsTmp );
 
 1212#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
 1213  const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
 
 1214  if ( coordinateEpoch > 0 )
 
 
 1224    OGRSpatialReferenceH ogrSrs = 
nullptr;
 
 1232    if ( !authId.isEmpty() )
 
 1234      ogrSrs = OSRNewSpatialReference( 
nullptr );
 
 1235      if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
 
 1238        OGRSpatialReferenceH ogrSrsFromWkt = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
 
 1239        if ( ogrSrsFromWkt )
 
 1241          if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
 
 1243            OSRDestroySpatialReference( ogrSrs );
 
 1244            ogrSrs = ogrSrsFromWkt;
 
 1248            OSRDestroySpatialReference( ogrSrsFromWkt );
 
 1254        OSRDestroySpatialReference( ogrSrs );
 
 1260      ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
 
 1264      OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
 
 1265#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
 
 1280  const QString cpgEncoding = readShapefileEncodingFromCpg( path );
 
 1281  if ( !cpgEncoding.isEmpty() )
 
 1284  return readShapefileEncodingFromLdid( path );
 
 
 1290  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1291  return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_CPG" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 
 1297  QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1298  return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_LDID" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 
 1305  char **papszStyleString = CSLTokenizeString2( 
string.toUtf8().constData(), 
";",
 
 1307                            | CSLT_PRESERVEQUOTES
 
 1308                            | CSLT_PRESERVEESCAPES );
 
 1309  for ( 
int i = 0; papszStyleString[i] != 
nullptr; ++i )
 
 1315    const thread_local QRegularExpression sToolPartRx( QStringLiteral( 
"^(.*?)\\((.*)\\)$" ) );
 
 1316    const QString stylePart( papszStyleString[i] );
 
 1317    const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
 
 1318    if ( !match.hasMatch() )
 
 1321    const QString tool = match.captured( 1 );
 
 1322    const QString params = match.captured( 2 );
 
 1324    char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(), 
",", CSLT_HONOURSTRINGS
 
 1325                         | CSLT_PRESERVEESCAPES );
 
 1327    QVariantMap toolParts;
 
 1328    const thread_local QRegularExpression sToolParamRx( QStringLiteral( 
"^(.*?):(.*)$" ) );
 
 1329    for ( 
int j = 0; papszTokens[j] != 
nullptr; ++j )
 
 1331      const QString toolPart( papszTokens[j] );
 
 1332      const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
 
 1333      if ( !match.hasMatch() )
 
 1337      toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
 
 1339    CSLDestroy( papszTokens );
 
 1342    styles.insert( tool.toLower(), toolParts );
 
 1344  CSLDestroy( papszStyleString );
 
 
 1350  const QVariantMap styles = parseStyleString( 
string );
 
 1352  auto convertSize = []( 
const QString & size, 
double & value, 
Qgis::RenderUnit & unit )->
bool 
 1354    const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
 
 1355    const QRegularExpressionMatch match = sUnitRx.match( size );
 
 1356    if ( match.hasMatch() )
 
 1358      value = match.captured( 1 ).toDouble();
 
 1359      const QString unitString = match.captured( 2 );
 
 1360      if ( unitString.compare( QLatin1String( 
"px" ), Qt::CaseInsensitive ) == 0 )
 
 1364        static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
 
 1365        static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
 
 1367        value *= PX_TO_PT_FACTOR;
 
 1370      else if ( unitString.compare( QLatin1String( 
"pt" ), Qt::CaseInsensitive ) == 0 )
 
 1375      else if ( unitString.compare( QLatin1String( 
"mm" ), Qt::CaseInsensitive ) == 0 )
 
 1380      else if ( unitString.compare( QLatin1String( 
"cm" ), Qt::CaseInsensitive ) == 0 )
 
 1386      else if ( unitString.compare( QLatin1String( 
"in" ), Qt::CaseInsensitive ) == 0 )
 
 1391      else if ( unitString.compare( QLatin1String( 
"g" ), Qt::CaseInsensitive ) == 0 )
 
 1396      QgsDebugError( QStringLiteral( 
"Unknown unit %1" ).arg( unitString ) );
 
 1400      QgsDebugError( QStringLiteral( 
"Could not parse style size %1" ).arg( size ) );
 
 1405  auto convertColor = []( 
const QString & string ) -> QColor
 
 1407    if ( 
string.isEmpty() )
 
 1410    const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral( 
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
 
 1411    const QRegularExpressionMatch match = sColorWithAlphaRx.match( 
string );
 
 1412    if ( match.hasMatch() )
 
 1415      return QColor( QStringLiteral( 
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
 
 1419      return QColor( 
string );
 
 1423  auto convertPen = [&convertColor, &convertSize, string]( 
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
 
 1425    QColor color = convertColor( lineStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1429    convertSize( lineStyle.value( QStringLiteral( 
"w" ) ).toString(), lineWidth, lineWidthUnit );
 
 1432    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-pen-(\\d+)" ) );
 
 1433    const QRegularExpressionMatch match = sMapInfoId.match( 
string );
 
 1434    if ( match.hasMatch() )
 
 1436      const int penId = match.captured( 1 ).toInt();
 
 1443    auto simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
 
 1444    simpleLine->setWidthUnit( lineWidthUnit );
 
 1447    const QString pattern = lineStyle.value( QStringLiteral( 
"p" ) ).toString();
 
 1448    if ( !pattern.isEmpty() )
 
 1450      const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
 
 1451      const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
 
 1452      if ( match.hasMatch() )
 
 1454        const QStringList patternValues = match.captured( 1 ).split( 
' ' );
 
 1455        QVector< qreal > dashPattern;
 
 1457        for ( 
const QString &val : patternValues )
 
 1460          convertSize( val + match.captured( 2 ), length, patternUnits );
 
 1461          dashPattern.push_back( length * lineWidth * 2 );
 
 1464        simpleLine->setCustomDashVector( dashPattern );
 
 1465        simpleLine->setCustomDashPatternUnit( patternUnits );
 
 1466        simpleLine->setUseCustomDashPattern( 
true );
 
 1470    Qt::PenCapStyle capStyle = Qt::FlatCap;
 
 1471    Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
 
 1473    const QString 
id = lineStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1474    if ( 
id.contains( QLatin1String( 
"mapinfo-pen" ), Qt::CaseInsensitive ) )
 
 1479      capStyle = Qt::RoundCap;
 
 1480      joinStyle = Qt::RoundJoin;
 
 1484    const QString penCap = lineStyle.value( QStringLiteral( 
"cap" ) ).toString();
 
 1485    if ( penCap.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1487      capStyle = Qt::FlatCap;
 
 1489    else if ( penCap.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1491      capStyle = Qt::RoundCap;
 
 1493    else if ( penCap.compare( QLatin1String( 
"p" ), Qt::CaseInsensitive ) == 0 )
 
 1495      capStyle = Qt::SquareCap;
 
 1497    simpleLine->setPenCapStyle( capStyle );
 
 1500    const QString penJoin = lineStyle.value( QStringLiteral( 
"j" ) ).toString();
 
 1501    if ( penJoin.compare( QLatin1String( 
"m" ), Qt::CaseInsensitive ) == 0 )
 
 1503      joinStyle = Qt::MiterJoin;
 
 1505    else if ( penJoin.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1507      joinStyle = Qt::RoundJoin;
 
 1509    else if ( penJoin.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1511      joinStyle = Qt::BevelJoin;
 
 1513    simpleLine->setPenJoinStyle( joinStyle );
 
 1515    const QString priority = lineStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1516    if ( !priority.isEmpty() )
 
 1518      simpleLine->setRenderingPass( priority.toInt() );
 
 1520    return std::make_unique< QgsLineSymbol >( 
QgsSymbolLayerList() << simpleLine.release() );
 
 1523  auto convertBrush = [&convertColor]( 
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
 
 1525    const QColor foreColor = convertColor( brushStyle.value( QStringLiteral( 
"fc" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1526    const QColor backColor = convertColor( brushStyle.value( QStringLiteral( 
"bc" ), QString() ).toString() );
 
 1528    const QString 
id = brushStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1531    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-brush-(\\d+)" ) );
 
 1532    const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1533    if ( match.hasMatch() )
 
 1535      const int brushId = match.captured( 1 ).toInt();
 
 1542    const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-brush-(\\d+)" ) );
 
 1543    const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1545    Qt::BrushStyle style = Qt::SolidPattern;
 
 1546    if ( ogrMatch.hasMatch() )
 
 1548      const int brushId = ogrMatch.captured( 1 ).toInt();
 
 1552          style = Qt::SolidPattern;
 
 1556          style = Qt::NoBrush;
 
 1560          style = Qt::HorPattern;
 
 1564          style = Qt::VerPattern;
 
 1568          style = Qt::FDiagPattern;
 
 1572          style = Qt::BDiagPattern;
 
 1576          style = Qt::CrossPattern;
 
 1580          style = Qt::DiagCrossPattern;
 
 1586    if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
 
 1588      auto backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
 
 1589      backgroundFill->setLocked( 
true );
 
 1590      backgroundFill->setStrokeStyle( Qt::NoPen );
 
 1591      layers << backgroundFill.release();
 
 1594    auto foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
 
 1595    foregroundFill->setBrushStyle( style );
 
 1596    foregroundFill->setStrokeStyle( Qt::NoPen );
 
 1598    const QString priority = brushStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1599    if ( !priority.isEmpty() )
 
 1601      foregroundFill->setRenderingPass( priority.toInt() );
 
 1603    layers << foregroundFill.release();
 
 1604    return std::make_unique< QgsFillSymbol >( layers );
 
 1607  auto convertSymbol = [&convertColor, &convertSize, string]( 
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
 
 1609    const QColor color = convertColor( symbolStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1613    convertSize( symbolStyle.value( QStringLiteral( 
"s" ) ).toString(), symbolSize, symbolSizeUnit );
 
 1615    const double angle = symbolStyle.value( QStringLiteral( 
"a" ), QStringLiteral( 
"0" ) ).toDouble();
 
 1617    const QString 
id = symbolStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1620    const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-sym-(\\d+)" ) );
 
 1621    const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1622    if ( match.hasMatch() )
 
 1624      const int symbolId = match.captured( 1 ).toInt();
 
 1635    std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
 
 1637    const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral( 
"font-sym-(\\d+)" ) );
 
 1638    const QRegularExpressionMatch fontMatch = sFontId.match( 
id );
 
 1639    if ( fontMatch.hasMatch() )
 
 1641      const int symId = fontMatch.captured( 1 ).toInt();
 
 1642      const QStringList families = symbolStyle.value( QStringLiteral( 
"f" ), QString() ).toString().split( 
',' );
 
 1644      bool familyFound = 
false;
 
 1647      for ( 
const QString &family : std::as_const( families ) )
 
 1655          fontFamily = processedFamily;
 
 1662        auto fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
 
 1663        fontMarker->setSizeUnit( symbolSizeUnit );
 
 1664        fontMarker->setAngle( -angle );
 
 1666        fontMarker->setColor( color );
 
 1668        const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1669        if ( strokeColor.isValid() )
 
 1671          fontMarker->setStrokeColor( strokeColor );
 
 1672          fontMarker->setStrokeWidth( 1 );
 
 1677          fontMarker->setStrokeWidth( 0 );
 
 1680        markerLayer = std::move( fontMarker );
 
 1682      else if ( !families.empty() )
 
 1691      const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-sym-(\\d+)" ) );
 
 1692      const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1695      bool isFilled = 
true;
 
 1696      if ( ogrMatch.hasMatch() )
 
 1698        const int symId = ogrMatch.captured( 1 ).toInt();
 
 1761      auto simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
 
 1762      simpleMarker->setSizeUnit( symbolSizeUnit );
 
 1763      simpleMarker->setStrokeWidth( 1.0 );
 
 1768        simpleMarker->setColor( color );
 
 1769        simpleMarker->setStrokeStyle( Qt::NoPen );
 
 1773        simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
 
 1774        simpleMarker->setStrokeColor( color );
 
 1777      const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1778      if ( strokeColor.isValid() )
 
 1780        simpleMarker->setStrokeColor( strokeColor );
 
 1781        simpleMarker->setStrokeStyle( Qt::SolidLine );
 
 1784      markerLayer = std::move( simpleMarker );
 
 1787    return std::make_unique< QgsMarkerSymbol >( 
QgsSymbolLayerList() << markerLayer.release() );
 
 1793      if ( styles.contains( QStringLiteral( 
"symbol" ) ) )
 
 1795        const QVariantMap symbolStyle = styles.value( QStringLiteral( 
"symbol" ) ).toMap();
 
 1796        return convertSymbol( symbolStyle );
 
 1804      if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1807        const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1808        return convertPen( lineStyle );
 
 1817      std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
 
 1818      if ( styles.contains( QStringLiteral( 
"brush" ) ) )
 
 1820        const QVariantMap brushStyle = styles.value( QStringLiteral( 
"brush" ) ).toMap();
 
 1821        fillSymbol = convertBrush( brushStyle );
 
 1825        auto emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
 
 1826        emptyFill->setBrushStyle( Qt::NoBrush );
 
 1827        fillSymbol = std::make_unique< QgsFillSymbol >( 
QgsSymbolLayerList() << emptyFill.release() );
 
 1830      std::unique_ptr< QgsSymbol > penSymbol;
 
 1831      if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1833        const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1834        penSymbol = convertPen( lineStyle );
 
 1839        const int count = penSymbol->symbolLayerCount();
 
 1849        for ( 
int i = 0; i < count; ++i )
 
 1851          std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
 
 1852          layer->setLocked( 
true );
 
 1853          fillSymbol->appendSymbolLayer( layer.release() );
 
 
 1869  variantType = QMetaType::Type::UnknownType;
 
 1870  variantSubType = QMetaType::Type::UnknownType;
 
 1875      if ( ogrSubType == OFSTBoolean )
 
 1877        variantType = QMetaType::Type::Bool;
 
 1880        variantType = QMetaType::Type::Int;
 
 1883      variantType = QMetaType::Type::LongLong;
 
 1886      variantType = QMetaType::Type::Double;
 
 1889      variantType = QMetaType::Type::QDate;
 
 1892      variantType = QMetaType::Type::QTime;
 
 1895      variantType = QMetaType::Type::QDateTime;
 
 1899      variantType = QMetaType::Type::QByteArray;
 
 1904      if ( ogrSubType == OFSTJSON )
 
 1906        variantType = QMetaType::Type::QVariantMap;
 
 1907        variantSubType = QMetaType::Type::QString;
 
 1911        variantType = QMetaType::Type::QString;
 
 1916    case OFTWideStringList:
 
 1917      variantType = QMetaType::Type::QStringList;
 
 1918      variantSubType = QMetaType::Type::QString;
 
 1921    case OFTIntegerList:
 
 1922      variantType = QMetaType::Type::QVariantList;
 
 1923      variantSubType = QMetaType::Type::Int;
 
 1927      variantType = QMetaType::Type::QVariantList;
 
 1928      variantSubType = QMetaType::Type::Double;
 
 1931    case OFTInteger64List:
 
 1932      variantType = QMetaType::Type::QVariantList;
 
 1933      variantSubType = QMetaType::Type::LongLong;
 
 
 1940  ogrSubType = OFSTNone;
 
 1941  switch ( variantType )
 
 1943    case QMetaType::Type::Bool:
 
 1944      ogrType = OFTInteger;
 
 1945      ogrSubType = OFSTBoolean;
 
 1948    case QMetaType::Type::Int:
 
 1949      ogrType = OFTInteger;
 
 1952    case QMetaType::Type::LongLong:
 
 1953      ogrType = OFTInteger64;
 
 1956    case QMetaType::Type::Double:
 
 1960    case QMetaType::Type::QChar:
 
 1961    case QMetaType::Type::QString:
 
 1962      ogrType = OFTString;
 
 1965    case QMetaType::Type::QStringList:
 
 1966      ogrType = OFTStringList;
 
 1969    case QMetaType::Type::QByteArray:
 
 1970      ogrType = OFTBinary;
 
 1973    case QMetaType::Type::QDate:
 
 1977    case QMetaType::Type::QTime:
 
 1980    case QMetaType::Type::QDateTime:
 
 1981      ogrType = OFTDateTime;
 
 1985      ogrType = OFTString;
 
 
 1992  if ( 
string.isEmpty() )
 
 2000      res = 
string.toInt( &ok );
 
 2004      res = 
string.toLongLong( &ok );
 
 2008      res = 
string.toDouble( &ok );
 
 2018      res = QDate::fromString( 
string, Qt::ISODate );
 
 2023      res = QTime::fromString( 
string, Qt::ISODate );
 
 2028      res = QDateTime::fromString( 
string, Qt::ISODate );
 
 2038  return ok ? res : QVariant();
 
 
 2046  const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
 
 2048  int nMaxIntLen = 11;
 
 2049  int nMaxInt64Len = 21;
 
 2050  int nMaxDoubleLen = 20;
 
 2051  int nMaxDoublePrec = 15;
 
 2053  if ( driverName == QLatin1String( 
"GPKG" ) )
 
 2063  QList<QgsVectorDataProvider::NativeType> nativeTypes;
 
 2067      << 
QgsVectorDataProvider::NativeType( QObject::tr( 
"Decimal number (real)" ), QStringLiteral( 
"double" ), QMetaType::Type::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
 
 2070  if ( driverName == QLatin1String( 
"GPKG" ) )
 
 2071    nativeTypes << 
QgsVectorDataProvider::NativeType( QObject::tr( 
"JSON (string)" ), QStringLiteral( 
"JSON" ), QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
 
 2073  bool supportsDate = 
true;
 
 2074  bool supportsTime = 
true;
 
 2075  bool supportsDateTime = 
true;
 
 2076  bool supportsBinary = 
false;
 
 2077  bool supportIntegerList = 
false;
 
 2078  bool supportInteger64List = 
false;
 
 2079  bool supportRealList = 
false;
 
 2080  bool supportsStringList = 
false;
 
 2084  if ( 
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES, 
nullptr ) )
 
 2086    char **papszTokens = CSLTokenizeString2( pszDataTypes, 
" ", 0 );
 
 2087    supportsDate = CSLFindString( papszTokens, 
"Date" ) >= 0;
 
 2088    supportsTime = CSLFindString( papszTokens, 
"Time" ) >= 0;
 
 2089    supportsDateTime = CSLFindString( papszTokens, 
"DateTime" ) >= 0;
 
 2090    supportsBinary = CSLFindString( papszTokens, 
"Binary" ) >= 0;
 
 2091    supportIntegerList = CSLFindString( papszTokens, 
"IntegerList" ) >= 0;
 
 2092    supportInteger64List = CSLFindString( papszTokens, 
"Integer64List" ) >= 0;
 
 2093    supportRealList = CSLFindString( papszTokens, 
"RealList" ) >= 0;
 
 2094    supportsStringList = CSLFindString( papszTokens, 
"StringList" ) >= 0;
 
 2095    CSLDestroy( papszTokens );
 
 2100#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0) 
 2101  if ( driverName == QLatin1String( 
"ESRI Shapefile" ) )
 
 2103    supportsDateTime = 
false;
 
 2117  if ( supportsDateTime )
 
 2122  if ( supportsBinary )
 
 2127  if ( supportIntegerList )
 
 2132  if ( supportInteger64List )
 
 2137  if ( supportRealList )
 
 2142  if ( supportsStringList )
 
 2148  const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES, 
nullptr );
 
 2149  if ( pszDataSubTypes && strstr( pszDataSubTypes, 
"Boolean" ) )
 
 
 2160#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0) 
 2166  const QString name{ OGR_FldDomain_GetName( domain ) };
 
 2167  const QString description{ OGR_FldDomain_GetDescription( domain ) };
 
 2169  QMetaType::Type fieldType = QMetaType::Type::UnknownType;
 
 2170  QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
 
 2171  const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
 
 2172  const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
 
 2173  ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
 
 2175  std::unique_ptr< QgsFieldDomain > res;
 
 2176  switch ( OGR_FldDomain_GetDomainType( domain ) )
 
 2180      QList< QgsCodedValue > values;
 
 2181      const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
 
 2182      while ( codedValue && codedValue->pszCode )
 
 2184        const QString code( codedValue->pszCode );
 
 2189        const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
 
 2190        values.append( 
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
 
 2195      res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
 
 2202      bool minIsInclusive = 
false;
 
 2203      if ( 
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
 
 2208      bool maxIsInclusive = 
false;
 
 2209      if ( 
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
 
 2214      res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
 
 2215            minValue, minIsInclusive,
 
 2216            maxValue, maxIsInclusive );
 
 2221      res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
 
 2222            QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
 
 2226  switch ( OGR_FldDomain_GetMergePolicy( domain ) )
 
 2228    case OFDMP_DEFAULT_VALUE:
 
 2234    case OFDMP_GEOMETRY_WEIGHTED:
 
 2239  switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
 
 2241    case OFDSP_DEFAULT_VALUE:
 
 2244    case OFDSP_DUPLICATE:
 
 2247    case OFDSP_GEOMETRY_RATIO:
 
 
 2259  OGRFieldType domainFieldType = OFTInteger;
 
 2260  OGRFieldSubType domainFieldSubType = OFSTNone;
 
 2261  variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
 
 2263  OGRFieldDomainH res = 
nullptr;
 
 2264  switch ( domain->
type() )
 
 2268      std::vector< OGRCodedValue > enumeration;
 
 2269      const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
 
 2270      enumeration.reserve( values.size() );
 
 2273        OGRCodedValue codedValue;
 
 2274        codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
 
 2275        codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
 
 2276        enumeration.push_back( codedValue );
 
 2279      last.pszCode = 
nullptr;
 
 2280      last.pszValue = 
nullptr;
 
 2281      enumeration.push_back( last );
 
 2282      res = OGR_CodedFldDomain_Create(
 
 2283              domain->
name().toUtf8().constData(),
 
 2290      for ( 
const OGRCodedValue &value : std::as_const( enumeration ) )
 
 2292        CPLFree( value.pszCode );
 
 2293        CPLFree( value.pszValue );
 
 2300      std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
 
 2301      std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
 
 2304      res = OGR_RangeFldDomain_Create(
 
 2305              domain->
name().toUtf8().constData(),
 
 2310              qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
 
 2312              qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
 
 2319      res = OGR_GlobFldDomain_Create(
 
 2320              domain->
name().toUtf8().constData(),
 
 2324              qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
 
 2333      OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
 
 2336      OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
 
 2339      OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
 
 2354      OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
 
 2357      OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
 
 2360      OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
 
 
 2373#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0) 
 2377  const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
 
 2379  const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
 
 2381  QVariantMap leftTableUriParts = datasetUriParts;
 
 2382  leftTableUriParts.insert( QStringLiteral( 
"layerName" ), leftTableName );
 
 2383  const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
 
 2385  const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
 
 2386  QVariantMap rightTableUriParts = datasetUriParts;
 
 2387  rightTableUriParts.insert( QStringLiteral( 
"layerName" ), rightTableName );
 
 2388  const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
 
 2390  const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
 
 2391  QString mappingTableSource;
 
 2392  if ( !mappingTableName.isEmpty() )
 
 2394    QVariantMap mappingTableUriParts = datasetUriParts;
 
 2395    mappingTableUriParts.insert( QStringLiteral( 
"layerName" ), mappingTableName );
 
 2396    mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
 
 2399  const QString relationshipName( GDALRelationshipGetName( relationship ) );
 
 2401  char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
 
 2403  CSLDestroy( cslLeftTableFieldNames );
 
 2405  char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
 
 2407  CSLDestroy( cslRightTableFieldNames );
 
 2409  char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
 
 2411  CSLDestroy( cslLeftMappingTableFieldNames );
 
 2413  char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
 
 2415  CSLDestroy( cslRightMappingTableFieldNames );
 
 2417  const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
 
 2418  const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
 
 2419  const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
 
 2421  const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
 
 2423  switch ( relationshipType )
 
 2429    case GRT_ASSOCIATION:
 
 2433    case GRT_AGGREGATION:
 
 2434      QgsLogger::warning( 
"Aggregation relationships are not supported, treating as association instead" );
 
 2438  const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
 
 2440  switch ( eCardinality )
 
 2442    case GRC_ONE_TO_ONE:
 
 2445    case GRC_ONE_TO_MANY:
 
 2448    case GRC_MANY_TO_ONE:
 
 2451    case GRC_MANY_TO_MANY:
 
 2456  switch ( cardinality )
 
 2465                           QString(), QString(), rightTableSource, QStringLiteral( 
"ogr" ),
 
 2466                           QString(), QString(), leftTableSource, QStringLiteral( 
"ogr" ) );
 
 2481                           QString(), QString(), rightTableSource, QStringLiteral( 
"ogr" ),
 
 2482                           QString(), QString(), leftTableSource, QStringLiteral( 
"ogr" ) );
 
 
 2500  GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
 
 2504      gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
 
 2507      gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
 
 2510      gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
 
 2513      gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
 
 2520  const QString leftTableName = leftParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2521  if ( leftTableName.isEmpty() )
 
 2523    error = QObject::tr( 
"Parent table name was not set" );
 
 2528  const QString rightTableName = rightParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2529  if ( rightTableName.isEmpty() )
 
 2531    error = QObject::tr( 
"Child table name was not set" );
 
 2535  if ( leftParts.value( QStringLiteral( 
"path" ) ).toString() != rightParts.value( QStringLiteral( 
"path" ) ).toString() )
 
 2537    error = QObject::tr( 
"Parent and child table must be from the same dataset" );
 
 2541  QString mappingTableName;
 
 2545    mappingTableName = mappingParts.value( QStringLiteral( 
"layerName" ) ).toString();
 
 2546    if ( leftParts.value( QStringLiteral( 
"path" ) ).toString() != mappingParts.value( QStringLiteral( 
"path" ) ).toString() )
 
 2548      error = QObject::tr( 
"Parent and mapping table must be from the same dataset" );
 
 2554      leftTableName.toLocal8Bit().constData(),
 
 2555      rightTableName.toLocal8Bit().constData(),
 
 2560  int count = leftFieldNames.count();
 
 2561  char **lst = 
nullptr;
 
 2564    for ( 
const QString &
string : leftFieldNames )
 
 2566      lst = CSLAddString( lst, 
string.toLocal8Bit().constData() );
 
 2569  GDALRelationshipSetLeftTableFields( relationH.get(), lst );
 
 2574  count = rightFieldNames.count();
 
 2578    for ( 
const QString &
string : rightFieldNames )
 
 2580      lst = CSLAddString( lst, 
string.toLocal8Bit().constData() );
 
 2583  GDALRelationshipSetRightTableFields( relationH.get(), lst );
 
 2586  if ( !mappingTableName.isEmpty() )
 
 2588    GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
 
 2592    int count = leftFieldNames.count();
 
 2596      for ( 
const QString &
string : leftFieldNames )
 
 2598        lst = CSLAddString( lst, 
string.toLocal8Bit().constData() );
 
 2601    GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
 
 2606    count = rightFieldNames.count();
 
 2610      for ( 
const QString &
string : rightFieldNames )
 
 2612        lst = CSLAddString( lst, 
string.toLocal8Bit().constData() );
 
 2615    GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
 
 2623      GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
 
 2627      GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
 
 2633    GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
 
 2635    GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
 
 2639    GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
 
 
 2647  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2651    errCause = QObject::tr( 
"No styles available on DB" );
 
 2655  if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
 
 2658    errCause = QObject::tr( 
"No styles available on DB" );
 
 2662  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2664  OGR_L_ResetReading( hLayer );
 
 2666  QList<qlonglong> listTimestamp;
 
 2667  QMap<int, QString> mapIdToStyleName;
 
 2668  QMap<int, QString> mapIdToDescription;
 
 2669  QMap<qlonglong, QList<int> > mapTimestampToId;
 
 2670  int numberOfRelatedStyles = 0;
 
 2678    QString tableName( QString::fromUtf8(
 
 2679                         OGR_F_GetFieldAsString( hFeature.get(),
 
 2680                             OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_name" ) ) ) );
 
 2681    QString geometryColumn( QString::fromUtf8(
 
 2682                              OGR_F_GetFieldAsString( hFeature.get(),
 
 2683                                  OGR_FD_GetFieldIndex( hLayerDefn, 
"f_geometry_column" ) ) ) );
 
 2684    QString styleName( QString::fromUtf8(
 
 2685                         OGR_F_GetFieldAsString( hFeature.get(),
 
 2686                             OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) ) );
 
 2687    QString description( QString::fromUtf8(
 
 2688                           OGR_F_GetFieldAsString( hFeature.get(),
 
 2689                               OGR_FD_GetFieldIndex( hLayerDefn, 
"description" ) ) ) );
 
 2690    int fid = 
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
 
 2691    if ( tableName == layerName &&
 
 2692         geometryColumn == geomColumn )
 
 2695      QString id( QString::number( fid ) );
 
 2697      names.append( styleName );
 
 2698      descriptions.append( description );
 
 2699      ++ numberOfRelatedStyles;
 
 2703      int  year, month, day, hour, minute, second, TZ;
 
 2704      OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"update_time" ),
 
 2705                                &year, &month, &day, &hour, &minute, &second, &TZ );
 
 2706      const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
 
 2707                           static_cast<qlonglong
>( month ) * 31 * 24 * 3600 + 
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
 
 2709      listTimestamp.append( ts );
 
 2710      mapIdToStyleName[fid] = styleName;
 
 2711      mapIdToDescription[fid] = description;
 
 2712      mapTimestampToId[ts].append( fid );
 
 2716  std::sort( listTimestamp.begin(), listTimestamp.end() );
 
 2718  for ( 
int i = listTimestamp.size() - 1; i >= 0; i-- )
 
 2720    const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
 
 2721    for ( 
int j = 0; j < listId.size(); j++ )
 
 2723      int fid = listId[j];
 
 2724      QString id( QString::number( fid ) );
 
 2726      names.append( mapIdToStyleName[fid] );
 
 2727      descriptions.append( mapIdToDescription[fid] );
 
 2731  return numberOfRelatedStyles;
 
 
 2739  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2743  const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
 
 2745  const QString checkQuery = QStringLiteral( 
"f_table_schema=''" 
 2746                             " AND f_table_name=%1" 
 2747                             " AND f_geometry_column=%2" 
 2748                             " AND styleName=%3" )
 
 2749                             .arg( QgsOgrProviderUtils::quotedValue( layerName ),
 
 2750                                   QgsOgrProviderUtils::quotedValue( geomColumn ),
 
 2751                                   QgsOgrProviderUtils::quotedValue( realStyleId ) );
 
 2752  OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
 
 2753  OGR_L_ResetReading( hLayer );
 
 2755  OGR_L_ResetReading( hLayer );
 
 
 2765  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2769    errCause = QObject::tr( 
"No styles available on DB" );
 
 2774  int id = styleId.toInt( &ok );
 
 2777    errCause = QObject::tr( 
"Invalid style identifier" );
 
 2784    errCause = QObject::tr( 
"No style corresponding to style identifier" );
 
 2788  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2789  QString styleQML( QString::fromUtf8(
 
 2790                      OGR_F_GetFieldAsString( hFeature.get(),
 
 2791                          OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) ) );
 
 2792  OGR_L_ResetReading( hLayer );
 
 
 2801  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2806    errCause = QObject::tr( 
"Connection to database failed" );
 
 2811    if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
 
 2813      errCause = QObject::tr( 
"Error executing the delete query." );
 
 
 2826  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2830    errCause = QObject::tr( 
"No styles available on DB" );
 
 2834  QString selectQmlQuery = QStringLiteral( 
"f_table_schema=''" 
 2835                           " AND f_table_name=%1" 
 2836                           " AND f_geometry_column=%2" 
 2837                           " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END" 
 2838                           ",update_time DESC" )
 
 2839                           .arg( QgsOgrProviderUtils::quotedValue( layerName ),
 
 2840                                 QgsOgrProviderUtils::quotedValue( geomColumn ) );
 
 2841  OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
 
 2842  OGR_L_ResetReading( hLayer );
 
 2843  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2845  qlonglong moreRecentTimestamp = 0;
 
 2851    if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ) ) )
 
 2853      styleQML = QString::fromUtf8(
 
 2854                   OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) );
 
 2855      styleName = QString::fromUtf8(
 
 2856                    OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) );
 
 2860    int  year, month, day, hour, minute, second, TZ;
 
 2861    OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"update_time" ),
 
 2862                              &year, &month, &day, &hour, &minute, &second, &TZ );
 
 2863    qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
 
 2864                   static_cast<qlonglong
>( month ) * 31 * 24 * 3600 + 
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
 
 2865    if ( ts > moreRecentTimestamp )
 
 2867      moreRecentTimestamp = ts;
 
 2868      styleQML = QString::fromUtf8(
 
 2869                   OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ) ) );
 
 2870      styleName = QString::fromUtf8(
 
 2871                    OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ) ) );
 
 2874  OGR_L_ResetReading( hLayer );
 
 
 2880  GDALDatasetH hDS, 
const QString &layerName, 
const QString &geomColumn, 
const QString &qmlStyle, 
const QString &sldStyle,
 
 2881  const QString &styleName, 
const QString &styleDescription,
 
 2882  const QString &uiFileContent, 
bool useAsDefault, QString &errCause
 
 2886  OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS, 
"layer_styles" );
 
 2893    char **options = 
nullptr;
 
 2895    options = CSLSetNameValue( options, 
"FID", 
"id" );
 
 2896    hLayer = GDALDatasetCreateLayer( hDS, 
"layer_styles", 
nullptr, wkbNone, options );
 
 2897    QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
 
 2898    CSLDestroy( options );
 
 2901      errCause = QObject::tr( 
"Unable to save layer style. It's not possible to create the destination table on the database." );
 
 2907      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2908      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2912      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2913      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2917      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2918      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2922      OGR_Fld_SetWidth( fld.get(), 256 );
 
 2923      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2927      OGR_Fld_SetWidth( fld.get(), 30 );
 
 2928      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2932      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2936      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2940      OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
 
 2941      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 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      OGR_Fld_SetWidth( fld.get(), 30 );
 
 2955      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2959      OGR_Fld_SetDefault( fld.get(), 
"CURRENT_TIMESTAMP" );
 
 2960      ok &= OGR_L_CreateField( hLayer, fld.get(), 
true ) == OGRERR_NONE;
 
 2964      errCause = QObject::tr( 
"Unable to save layer style. It's not possible to create the destination table on the database." );
 
 2969  QString realStyleName =
 
 2970    styleName.isEmpty() ? layerName : styleName;
 
 2972  OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
 
 2976    QString oldDefaultQuery = QStringLiteral( 
"useAsDefault = 1 AND f_table_schema=''" 
 2977                              " AND f_table_name=%1" 
 2978                              " AND f_geometry_column=%2" )
 
 2979                              .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
 
 2980                              .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
 
 2981    OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
 
 2985      OGR_F_SetFieldInteger( hFeature.get(),
 
 2986                             OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ),
 
 2988      bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
 
 2991        QgsDebugError( QStringLiteral( 
"Could not unset previous useAsDefault style" ) );
 
 2996  QString checkQuery = QStringLiteral( 
"f_table_schema=''" 
 2997                                       " AND f_table_name=%1" 
 2998                                       " AND f_geometry_column=%2" 
 2999                                       " AND styleName=%3" )
 
 3000                       .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
 
 3001                       .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
 
 3002                       .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
 
 3003  OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
 
 3004  OGR_L_ResetReading( hLayer );
 
 3006  OGR_L_ResetReading( hLayer );
 
 3015    hFeature.reset( OGR_F_Create( hLayerDefn ) );
 
 3016    OGR_F_SetFieldString( hFeature.get(),
 
 3017                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_catalog" ),
 
 3019    OGR_F_SetFieldString( hFeature.get(),
 
 3020                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_schema" ),
 
 3022    OGR_F_SetFieldString( hFeature.get(),
 
 3023                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_table_name" ),
 
 3024                          layerName.toUtf8().constData() );
 
 3025    OGR_F_SetFieldString( hFeature.get(),
 
 3026                          OGR_FD_GetFieldIndex( hLayerDefn, 
"f_geometry_column" ),
 
 3027                          geomColumn.toUtf8().constData() );
 
 3028    OGR_F_SetFieldString( hFeature.get(),
 
 3029                          OGR_FD_GetFieldIndex( hLayerDefn, 
"styleName" ),
 
 3030                          realStyleName.toUtf8().constData() );
 
 3031    if ( !uiFileContent.isEmpty() )
 
 3033      OGR_F_SetFieldString( hFeature.get(),
 
 3034                            OGR_FD_GetFieldIndex( hLayerDefn, 
"ui" ),
 
 3035                            uiFileContent.toUtf8().constData() );
 
 3038  OGR_F_SetFieldString( hFeature.get(),
 
 3039                        OGR_FD_GetFieldIndex( hLayerDefn, 
"styleQML" ),
 
 3040                        qmlStyle.toUtf8().constData() );
 
 3041  OGR_F_SetFieldString( hFeature.get(),
 
 3042                        OGR_FD_GetFieldIndex( hLayerDefn, 
"styleSLD" ),
 
 3043                        sldStyle.toUtf8().constData() );
 
 3044  OGR_F_SetFieldInteger( hFeature.get(),
 
 3045                         OGR_FD_GetFieldIndex( hLayerDefn, 
"useAsDefault" ),
 
 3046                         useAsDefault ? 1 : 0 );
 
 3047  OGR_F_SetFieldString( hFeature.get(),
 
 3048                        OGR_FD_GetFieldIndex( hLayerDefn, 
"description" ),
 
 3049                        ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
 
 3050  OGR_F_SetFieldString( hFeature.get(),
 
 3051                        OGR_FD_GetFieldIndex( hLayerDefn, 
"owner" ),
 
 3056    bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
 
 3058    bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
 
 3063    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...
 
@ SetToNull
Use a null value.
 
@ GeometryWeighted
New values are computed as the weighted average of the source values.
 
@ UnsetField
Clears the field value so that the data provider backend will populate using any backend triggers or ...
 
@ LargestGeometry
Use value from the feature with the largest geometry.
 
@ DefaultValue
Use default field value.
 
@ MaximumValue
Use the maximum value from the features-to-be-merged.
 
@ MinimumValue
Use the minimum value from the features-to-be-merged.
 
@ 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.
 
@ PolyhedralSurfaceM
PolyhedralSurfaceM.
 
@ 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.
 
@ PolyhedralSurfaceZM
PolyhedralSurfaceM.
 
@ MultiPolygonZ
MultiPolygonZ.
 
@ CurvePolygonZ
CurvePolygonZ.
 
@ CompoundCurveZ
CompoundCurveZ.
 
@ MultiCurveZ
MultiCurveZ.
 
@ MultiCurveM
MultiCurveM.
 
@ PolyhedralSurfaceZ
PolyhedralSurfaceZ.
 
@ CircularStringM
CircularStringM.
 
@ CurvePolygon
CurvePolygon.
 
@ CircularStringZ
CircularStringZ.
 
@ LineStringZ
LineStringZ.
 
@ PolyhedralSurface
PolyhedralSurface.
 
@ 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.
 
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.
 
QString typeName() const
Gets the field type.
 
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).
 
Abstract base class for fill symbol layers.
 
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 QVariant jsonToVariant(const json &value)
Converts a JSON value to a QVariant, in case of parsing error an invalid QVariant is returned.
 
Abstract base class for line symbol layers.
 
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, 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).
 
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.
 
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 Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
 
static Q_INVOKABLE 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...
 
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.