24 #include "qgsogrprovider.h" 
   41 #include <cpl_error.h> 
   42 #include <QJsonDocument> 
   45 #include <QTextStream> 
   46 #include <QDataStream> 
   47 #include <QRegularExpression> 
   49 #include "ogr_srs_api.h" 
   54   OGR_DS_Destroy( source );
 
   60   OGR_G_DestroyGeometry( geometry );
 
   65   OGR_Fld_Destroy( definition );
 
   70   OGR_F_Destroy( feature );
 
   87   CPLPushErrorHandler( CPLQuietErrorHandler );
 
   88   GDALDeleteDataset( driver, path.toUtf8().constData() );
 
  100   GDALDestroyWarpOptions( options );
 
  105   if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
 
  111       return value->Integer;
 
  114       return value->Integer64;
 
  121       return QString::fromUtf8( value->String );
 
  124       return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
 
  128       float secondsPart = 0;
 
  129       float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  130       return QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( 1000 * millisecondPart ) );
 
  135       float secondsPart = 0;
 
  136       float millisecondPart = std::modf( value->Date.Second, &secondsPart );
 
  137       return QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
 
  138                         QTime( value->Date.Hour, value->Date.Minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( 1000 * millisecondPart ) ) );
 
  143       Q_ASSERT_X( 
false, 
"QgsOgrUtils::OGRFieldtoVariant", 
"OFTBinary type not supported" );
 
  149       res.reserve( value->IntegerList.nCount );
 
  150       for ( 
int i = 0; i < value->IntegerList.nCount; ++i )
 
  151         res << value->IntegerList.paList[ i ];
 
  155     case OFTInteger64List:
 
  158       res.reserve( value->Integer64List.nCount );
 
  159       for ( 
int i = 0; i < value->Integer64List.nCount; ++i )
 
  160         res << value->Integer64List.paList[ i ];
 
  167       res.reserve( value->RealList.nCount );
 
  168       for ( 
int i = 0; i < value->RealList.nCount; ++i )
 
  169         res << value->RealList.paList[ i ];
 
  174     case OFTWideStringList:
 
  177       res.reserve( value->StringList.nCount );
 
  178       for ( 
int i = 0; i < value->StringList.nCount; ++i )
 
  179         res << QString::fromUtf8( value->StringList.paList[ i ] );
 
  195   feature.
setId( OGR_F_GetFID( ogrFet ) );
 
  198   if ( !readOgrFeatureGeometry( ogrFet, feature ) )
 
  203   if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
 
  218   int fieldCount = OGR_F_GetFieldCount( ogrFet );
 
  219   for ( 
int i = 0; i < fieldCount; ++i )
 
  221     OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
 
  228     QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
 
  229     QVariant::Type varType;
 
  230     switch ( OGR_Fld_GetType( fldDef ) )
 
  233         if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
 
  234           varType = QVariant::Bool;
 
  236           varType = QVariant::Int;
 
  239         varType = QVariant::LongLong;
 
  242         varType = QVariant::Double;
 
  245         varType = QVariant::Date;
 
  248         varType = QVariant::Time;
 
  251         varType = QVariant::DateTime;
 
  254         if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
 
  255           varType = QVariant::Map;
 
  257           varType = QVariant::String;
 
  260         varType = QVariant::String; 
 
  270   if ( attIndex < 0 || attIndex >= fields.
count() )
 
  278   return getOgrFeatureAttribute( ogrFet, 
field, attIndex, encoding, ok );
 
  283   if ( !ogrFet || attIndex < 0 )
 
  290   OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
 
  297     QgsDebugMsg( QStringLiteral( 
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
 
  306   if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
 
  310       case QVariant::String:
 
  313           value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  315           value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
 
  320         if ( value.isNull() )
 
  321           value = QVariant( QStringLiteral( 
"" ) ); 
 
  327         value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
 
  330         value = QVariant( 
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
 
  332       case QVariant::LongLong:
 
  333         value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
 
  335       case QVariant::Double:
 
  336         value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
 
  339       case QVariant::DateTime:
 
  342         int year, month, day, hour, minute, tzf;
 
  344         float secondsPart = 0;
 
  346         OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
 
  347         float millisecondPart = std::modf( second, &secondsPart );
 
  350           value = QDate( year, month, day );
 
  351         else if ( 
field.
type() == QVariant::Time )
 
  352           value = QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( 1000 * millisecondPart ) );
 
  354           value = QDateTime( QDate( year, month, day ),
 
  355                              QTime( hour, minute, 
static_cast< int >( secondsPart ), 
static_cast< int >( 1000 * millisecondPart ) ) );
 
  359       case QVariant::ByteArray:
 
  362         const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
 
  366         QByteArray ba = QByteArray::fromRawData( 
reinterpret_cast<const char *
>( b ), size );
 
  373       case QVariant::StringList:
 
  376         char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  377         const int count = CSLCount( lst );
 
  380           list.reserve( count );
 
  381           for ( 
int i = 0; i < count; i++ )
 
  384               list << encoding->toUnicode( lst[i] );
 
  386               list << QString::fromUtf8( lst[i] );
 
  397           case QVariant::String:
 
  400             char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
 
  401             const int count = CSLCount( lst );
 
  404               list.reserve( count );
 
  405               for ( 
int i = 0; i < count; i++ )
 
  408                   list << encoding->toUnicode( lst[i] );
 
  410                   list << QString::fromUtf8( lst[i] );
 
  421             const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
 
  424               list.reserve( count );
 
  425               for ( 
int i = 0; i < count; i++ )
 
  434           case QVariant::Double:
 
  438             const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
 
  441               list.reserve( count );
 
  442               for ( 
int i = 0; i < count; i++ )
 
  451           case QVariant::LongLong:
 
  455             const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
 
  458               list.reserve( count );
 
  459               for ( 
int i = 0; i < count; i++ )
 
  470             Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
  484           value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  486           value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
 
  490         Q_ASSERT_X( 
false, 
"QgsOgrUtils::getOgrFeatureAttribute", 
"unsupported field type" );
 
  513   for ( 
int idx = 0; idx < fields.
count(); ++idx )
 
  515     QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
 
  529   OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
 
  533     feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
 
  543   OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
 
  544   return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
 
  549   std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
 
  551   const int count = OGR_G_GetGeometryCount( geom );
 
  552   mp->reserve( count );
 
  553   for ( 
int i = 0; i < count; ++i )
 
  565   int count = OGR_G_GetPointCount( geom );
 
  566   QVector< double > x( count );
 
  567   QVector< double > y( count );
 
  569   double *pz = 
nullptr;
 
  575   double *pm = 
nullptr;
 
  582   OGR_G_GetPointsZM( geom, x.data(), 
sizeof( 
double ), y.data(), 
sizeof( 
double ), pz, 
sizeof( 
double ), pm, 
sizeof( 
double ) );
 
  589   std::unique_ptr< QgsMultiLineString > mp = std::make_unique< QgsMultiLineString >();
 
  591   const int count = OGR_G_GetGeometryCount( geom );
 
  592   mp->reserve( count );
 
  593   for ( 
int i = 0; i < count; ++i )
 
  603   std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
 
  605   const int count = OGR_G_GetGeometryCount( geom );
 
  611   for ( 
int i = 1; i < count; ++i )
 
  621   std::unique_ptr< QgsMultiPolygon > polygon = std::make_unique< QgsMultiPolygon >();
 
  623   const int count = OGR_G_GetGeometryCount( geom );
 
  624   polygon->reserve( count );
 
  625   for ( 
int i = 0; i < count; ++i )
 
  635   switch ( ogrGeomType )
 
  637     case wkbUnknown: 
return QgsWkbTypes::Type::Unknown;
 
  638     case wkbPoint: 
return QgsWkbTypes::Type::Point;
 
  639     case wkbLineString: 
return QgsWkbTypes::Type::LineString;
 
  640     case wkbPolygon: 
return QgsWkbTypes::Type::Polygon;
 
  641     case wkbMultiPoint: 
return QgsWkbTypes::Type::MultiPoint;
 
  642     case wkbMultiLineString: 
return QgsWkbTypes::Type::MultiLineString;
 
  643     case wkbMultiPolygon: 
return QgsWkbTypes::Type::MultiPolygon;
 
  644     case wkbGeometryCollection: 
return QgsWkbTypes::Type::GeometryCollection;
 
  645     case wkbCircularString: 
return QgsWkbTypes::Type::CircularString;
 
  646     case wkbCompoundCurve: 
return QgsWkbTypes::Type::CompoundCurve;
 
  647     case wkbCurvePolygon: 
return QgsWkbTypes::Type::CurvePolygon;
 
  648     case wkbMultiCurve: 
return QgsWkbTypes::Type::MultiCurve;
 
  649     case wkbMultiSurface: 
return QgsWkbTypes::Type::MultiSurface;
 
  650     case wkbCurve: 
return QgsWkbTypes::Type::Unknown; 
 
  651     case wkbSurface: 
return QgsWkbTypes::Type::Unknown; 
 
  652     case wkbPolyhedralSurface: 
return QgsWkbTypes::Type::Unknown; 
 
  653     case wkbTIN: 
return QgsWkbTypes::Type::Unknown; 
 
  654     case wkbTriangle: 
return QgsWkbTypes::Type::Triangle;
 
  656     case wkbNone: 
return QgsWkbTypes::Type::NoGeometry;
 
  657     case wkbLinearRing: 
return QgsWkbTypes::Type::LineString; 
 
  659     case wkbCircularStringZ: 
return QgsWkbTypes::Type::CircularStringZ;
 
  660     case wkbCompoundCurveZ: 
return QgsWkbTypes::Type::CompoundCurveZ;
 
  661     case wkbCurvePolygonZ: 
return QgsWkbTypes::Type::CurvePolygonZ;
 
  662     case wkbMultiCurveZ: 
return QgsWkbTypes::Type::MultiCurveZ;
 
  663     case wkbMultiSurfaceZ: 
return QgsWkbTypes::Type::MultiSurfaceZ;
 
  664     case wkbCurveZ: 
return QgsWkbTypes::Type::Unknown; 
 
  665     case wkbSurfaceZ: 
return QgsWkbTypes::Type::Unknown; 
 
  666     case wkbPolyhedralSurfaceZ: 
return QgsWkbTypes::Type::Unknown; 
 
  667     case wkbTINZ: 
return QgsWkbTypes::Type::Unknown; 
 
  668     case wkbTriangleZ: 
return QgsWkbTypes::Type::TriangleZ;
 
  670     case wkbPointM: 
return QgsWkbTypes::Type::PointM;
 
  671     case wkbLineStringM: 
return QgsWkbTypes::Type::LineStringM;
 
  672     case wkbPolygonM: 
return QgsWkbTypes::Type::PolygonM;
 
  673     case wkbMultiPointM: 
return QgsWkbTypes::Type::MultiPointM;
 
  674     case wkbMultiLineStringM: 
return QgsWkbTypes::Type::MultiLineStringM;
 
  675     case wkbMultiPolygonM: 
return QgsWkbTypes::Type::MultiPolygonM;
 
  676     case wkbGeometryCollectionM: 
return QgsWkbTypes::Type::GeometryCollectionM;
 
  677     case wkbCircularStringM: 
return QgsWkbTypes::Type::CircularStringM;
 
  678     case wkbCompoundCurveM: 
return QgsWkbTypes::Type::CompoundCurveM;
 
  679     case wkbCurvePolygonM: 
return QgsWkbTypes::Type::CurvePolygonM;
 
  680     case wkbMultiCurveM: 
return QgsWkbTypes::Type::MultiCurveM;
 
  681     case wkbMultiSurfaceM: 
return QgsWkbTypes::Type::MultiSurfaceM;
 
  682     case wkbCurveM: 
return QgsWkbTypes::Type::Unknown; 
 
  683     case wkbSurfaceM: 
return QgsWkbTypes::Type::Unknown; 
 
  684     case wkbPolyhedralSurfaceM: 
return QgsWkbTypes::Type::Unknown; 
 
  685     case wkbTINM: 
return QgsWkbTypes::Type::Unknown; 
 
  686     case wkbTriangleM: 
return QgsWkbTypes::Type::TriangleM;
 
  688     case wkbPointZM: 
return QgsWkbTypes::Type::PointZM;
 
  689     case wkbLineStringZM: 
return QgsWkbTypes::Type::LineStringZM;
 
  690     case wkbPolygonZM: 
return QgsWkbTypes::Type::PolygonZM;
 
  691     case wkbMultiPointZM: 
return QgsWkbTypes::Type::MultiPointZM;
 
  692     case wkbMultiLineStringZM: 
return QgsWkbTypes::Type::MultiLineStringZM;
 
  693     case wkbMultiPolygonZM: 
return QgsWkbTypes::Type::MultiPolygonZM;
 
  694     case wkbGeometryCollectionZM: 
return QgsWkbTypes::Type::GeometryCollectionZM;
 
  695     case wkbCircularStringZM: 
return QgsWkbTypes::Type::CircularStringZM;
 
  696     case wkbCompoundCurveZM: 
return QgsWkbTypes::Type::CompoundCurveZM;
 
  697     case wkbCurvePolygonZM: 
return QgsWkbTypes::Type::CurvePolygonZM;
 
  698     case wkbMultiCurveZM: 
return QgsWkbTypes::Type::MultiCurveZM;
 
  699     case wkbMultiSurfaceZM: 
return QgsWkbTypes::Type::MultiSurfaceZM;
 
  700     case wkbCurveZM: 
return QgsWkbTypes::Type::Unknown; 
 
  701     case wkbSurfaceZM: 
return QgsWkbTypes::Type::Unknown; 
 
  702     case wkbPolyhedralSurfaceZM: 
return QgsWkbTypes::Type::Unknown; 
 
  703     case wkbTINZM: 
return QgsWkbTypes::Type::Unknown; 
 
  704     case wkbTriangleZM: 
return QgsWkbTypes::Type::TriangleZM;
 
  706     case wkbPoint25D: 
return QgsWkbTypes::Type::PointZ;
 
  707     case wkbLineString25D: 
return QgsWkbTypes::Type::LineStringZ;
 
  708     case wkbPolygon25D: 
return QgsWkbTypes::Type::PolygonZ;
 
  709     case wkbMultiPoint25D: 
return QgsWkbTypes::Type::MultiPointZ;
 
  710     case wkbMultiLineString25D: 
return QgsWkbTypes::Type::MultiLineStringZ;
 
  711     case wkbMultiPolygon25D: 
return QgsWkbTypes::Type::MultiPolygonZ;
 
  712     case wkbGeometryCollection25D: 
return QgsWkbTypes::Type::GeometryCollectionZ;
 
  716   return QgsWkbTypes::Type::Unknown;
 
  724   const auto ogrGeomType = OGR_G_GetGeometryType( geom );
 
  767   if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
 
  770     if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
 
  771          wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
 
  773       auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
 
  774       auto ret = ogrGeometryToQgsGeometry( newGeom );
 
  775       OGR_G_DestroyGeometry( newGeom );
 
  781   int memorySize = OGR_G_WkbSize( geom );
 
  782   unsigned char *wkb = 
new unsigned char[memorySize];
 
  786   uint32_t origGeomType;
 
  787   memcpy( &origGeomType, wkb + 1, 
sizeof( uint32_t ) );
 
  788   bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
 
  789   bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
 
  792   if ( origGeomType % 1000 == 16 ) 
 
  795     int nDims = 2 + hasZ + hasM;
 
  798     unsigned char *wkbptr = wkb;
 
  804     memcpy( wkbptr, &newMultiType, 
sizeof( uint32_t ) );
 
  809     memcpy( &numGeoms, wkb + 5, 
sizeof( uint32_t ) );
 
  813     for ( uint32_t i = 0; i < numGeoms; ++i )
 
  819       memcpy( wkbptr, &newSingleType, 
sizeof( uint32_t ) );
 
  820       wkbptr += 
sizeof( uint32_t );
 
  824       memcpy( &nRings, wkbptr, 
sizeof( uint32_t ) );
 
  825       wkbptr += 
sizeof( uint32_t );
 
  827       for ( uint32_t j = 0; j < nRings; ++j )
 
  830         memcpy( &nPoints, wkbptr, 
sizeof( uint32_t ) );
 
  831         wkbptr += 
sizeof( uint32_t ) + 
sizeof( 
double ) * nDims * nPoints;
 
  835   else if ( origGeomType % 1000 == 15 ) 
 
  840     memcpy( wkb + 1, &newType, 
sizeof( uint32_t ) );
 
  851   if ( 
string.isEmpty() )
 
  854   QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
  857   QByteArray ba = 
string.toUtf8();
 
  858   VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
  859                                     static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
  864     VSIUnlink( randomFileName.toUtf8().constData() );
 
  868   OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
  872     VSIUnlink( randomFileName.toUtf8().constData() );
 
  877   while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
  879     QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
 
  885   VSIUnlink( randomFileName.toUtf8().constData() );
 
  893   if ( 
string.isEmpty() )
 
  896   QString randomFileName = QStringLiteral( 
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
 
  899   QByteArray ba = 
string.toUtf8();
 
  900   VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(), 
reinterpret_cast< GByte * 
>( ba.data() ),
 
  901                                     static_cast< vsi_l_offset 
>( ba.size() ), FALSE ) );
 
  906     VSIUnlink( randomFileName.toUtf8().constData() );
 
  910   OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
 
  914     VSIUnlink( randomFileName.toUtf8().constData() );
 
  920   if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
 
  922     fields = readOgrFields( oFeat.get(), encoding );
 
  926   VSIUnlink( randomFileName.toUtf8().constData() );
 
  935   for ( 
qgssize i = 0; stringList[i]; ++i )
 
  937     strings.append( QString::fromUtf8( stringList[i] ) );
 
  948   char *pszWkt = 
nullptr;
 
  949   const QByteArray multiLineOption = QStringLiteral( 
"MULTILINE=NO" ).toLocal8Bit();
 
  950   const QByteArray formatOption = QStringLiteral( 
"FORMAT=WKT2" ).toLocal8Bit();
 
  951   const char *
const options[] = {multiLineOption.constData(), formatOption.constData(), 
nullptr};
 
  952   OSRExportToWktEx( srs, &pszWkt, options );
 
  954   const QString res( pszWkt );
 
  961   const QString wkt = OGRSpatialReferenceToWkt( srs );
 
  965   const char *authorityName = OSRGetAuthorityName( srs, 
nullptr );
 
  966   const char *authorityCode = OSRGetAuthorityCode( srs, 
nullptr );
 
  968   if ( authorityName && authorityCode )
 
  970     QString authId = QString( authorityName ) + 
':' + QString( authorityCode );
 
  973     if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
 
  974          OSRIsSame( srs, ogrSrsTmp ) )
 
  979     OSRDestroySpatialReference( ogrSrsTmp );
 
  984 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
  985   const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
 
  986   if ( coordinateEpoch > 0 )
 
 1004     if ( !authId.isEmpty() )
 
 1006       ogrSrs = OSRNewSpatialReference( 
nullptr );
 
 1007       if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
 
 1011         if ( ogrSrsFromWkt )
 
 1013           if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
 
 1015             OSRDestroySpatialReference( ogrSrs );
 
 1016             ogrSrs = ogrSrsFromWkt;
 
 1020             OSRDestroySpatialReference( ogrSrsFromWkt );
 
 1026         OSRDestroySpatialReference( ogrSrs );
 
 1032       ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
 
 1036       OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
 
 1037 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0) 
 1052   const QString cpgEncoding = readShapefileEncodingFromCpg( path );
 
 1053   if ( !cpgEncoding.isEmpty() )
 
 1056   return readShapefileEncodingFromLdid( path );
 
 1061 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) 
 1063   QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1064   return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_CPG" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 1066   if ( !QFileInfo::exists( path ) )
 
 1070   const QFileInfo fi( path );
 
 1071   const QString baseName = fi.completeBaseName();
 
 1072   const QString cpgPath = fi.dir().filePath( QStringLiteral( 
"%1.%2" ).arg( baseName, fi.suffix() == QLatin1String( 
"SHP" ) ? QStringLiteral( 
"CPG" ) : QStringLiteral( 
"cpg" ) ) );
 
 1073   if ( QFile::exists( cpgPath ) )
 
 1075     QFile cpgFile( cpgPath );
 
 1076     if ( cpgFile.open( QIODevice::ReadOnly ) )
 
 1078       QTextStream cpgStream( &cpgFile );
 
 1079       const QString cpgString = cpgStream.readLine();
 
 1082       if ( !cpgString.isEmpty() )
 
 1087         int cpgCodePage = cpgString.toInt( &ok );
 
 1088         if ( ok && ( ( cpgCodePage >= 437 && cpgCodePage <= 950 )
 
 1089                      || ( cpgCodePage >= 1250 && cpgCodePage <= 1258 ) ) )
 
 1091           return QStringLiteral( 
"CP%1" ).arg( cpgCodePage );
 
 1093         else if ( cpgString.startsWith( QLatin1String( 
"8859" ) ) )
 
 1095           if ( cpgString.length() > 4 && cpgString.at( 4 ) == 
'-' )
 
 1096             return QStringLiteral( 
"ISO-8859-%1" ).arg( cpgString.mid( 5 ) );
 
 1098             return QStringLiteral( 
"ISO-8859-%1" ).arg( cpgString.mid( 4 ) );
 
 1100         else if ( cpgString.startsWith( QLatin1String( 
"UTF-8" ), Qt::CaseInsensitive ) ||
 
 1101                   cpgString.startsWith( QLatin1String( 
"UTF8" ), Qt::CaseInsensitive ) )
 
 1102           return QStringLiteral( 
"UTF-8" );
 
 1103         else if ( cpgString.startsWith( QLatin1String( 
"ANSI 1251" ), Qt::CaseInsensitive ) )
 
 1104           return QStringLiteral( 
"CP1251" );
 
 1117 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0) 
 1119   QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path, 
false, QStringList(), 0, errCause, 
false );
 
 1120   return layer ? layer->GetMetadataItem( QStringLiteral( 
"ENCODING_FROM_LDID" ), QStringLiteral( 
"SHAPEFILE" ) ) : QString();
 
 1125   if ( !QFileInfo::exists( path ) )
 
 1129   const QFileInfo fi( path );
 
 1130   const QString baseName = fi.completeBaseName();
 
 1133   const QString dbfPath = fi.dir().filePath( QStringLiteral( 
"%1.%2" ).arg( baseName, fi.suffix() == QLatin1String( 
"SHP" ) ? QStringLiteral( 
"DBF" ) : QStringLiteral( 
"dbf" ) ) );
 
 1134   if ( QFile::exists( dbfPath ) )
 
 1136     QFile dbfFile( dbfPath );
 
 1137     if ( dbfFile.open( QIODevice::ReadOnly ) )
 
 1140       QDataStream dbfIn( &dbfFile );
 
 1141       dbfIn.setByteOrder( QDataStream::LittleEndian );
 
 1151         case 1: nCP = 437;      
break;
 
 1152         case 2: nCP = 850;      
break;
 
 1153         case 3: nCP = 1252;     
break;
 
 1154         case 4: nCP = 10000;    
break;
 
 1155         case 8: nCP = 865;      
break;
 
 1156         case 10: nCP = 850;     
break;
 
 1157         case 11: nCP = 437;     
break;
 
 1158         case 13: nCP = 437;     
break;
 
 1159         case 14: nCP = 850;     
break;
 
 1160         case 15: nCP = 437;     
break;
 
 1161         case 16: nCP = 850;     
break;
 
 1162         case 17: nCP = 437;     
break;
 
 1163         case 18: nCP = 850;     
break;
 
 1164         case 19: nCP = 932;     
break;
 
 1165         case 20: nCP = 850;     
break;
 
 1166         case 21: nCP = 437;     
break;
 
 1167         case 22: nCP = 850;     
break;
 
 1168         case 23: nCP = 865;     
break;
 
 1169         case 24: nCP = 437;     
break;
 
 1170         case 25: nCP = 437;     
break;
 
 1171         case 26: nCP = 850;     
break;
 
 1172         case 27: nCP = 437;     
break;
 
 1173         case 28: nCP = 863;     
break;
 
 1174         case 29: nCP = 850;     
break;
 
 1175         case 31: nCP = 852;     
break;
 
 1176         case 34: nCP = 852;     
break;
 
 1177         case 35: nCP = 852;     
break;
 
 1178         case 36: nCP = 860;     
break;
 
 1179         case 37: nCP = 850;     
break;
 
 1180         case 38: nCP = 866;     
break;
 
 1181         case 55: nCP = 850;     
break;
 
 1182         case 64: nCP = 852;     
break;
 
 1183         case 77: nCP = 936;     
break;
 
 1184         case 78: nCP = 949;     
break;
 
 1185         case 79: nCP = 950;     
break;
 
 1186         case 80: nCP = 874;     
break;
 
 1187         case 87: 
return QStringLiteral( 
"ISO-8859-1" );
 
 1188         case 88: nCP = 1252;     
break;
 
 1189         case 89: nCP = 1252;     
break;
 
 1190         case 100: nCP = 852;     
break;
 
 1191         case 101: nCP = 866;     
break;
 
 1192         case 102: nCP = 865;     
break;
 
 1193         case 103: nCP = 861;     
break;
 
 1194         case 104: nCP = 895;     
break;
 
 1195         case 105: nCP = 620;     
break;
 
 1196         case 106: nCP = 737;     
break;
 
 1197         case 107: nCP = 857;     
break;
 
 1198         case 108: nCP = 863;     
break;
 
 1199         case 120: nCP = 950;     
break;
 
 1200         case 121: nCP = 949;     
break;
 
 1201         case 122: nCP = 936;     
break;
 
 1202         case 123: nCP = 932;     
break;
 
 1203         case 124: nCP = 874;     
break;
 
 1204         case 134: nCP = 737;     
break;
 
 1205         case 135: nCP = 852;     
break;
 
 1206         case 136: nCP = 857;     
break;
 
 1207         case 150: nCP = 10007;   
break;
 
 1208         case 151: nCP = 10029;   
break;
 
 1209         case 200: nCP = 1250;    
break;
 
 1210         case 201: nCP = 1251;    
break;
 
 1211         case 202: nCP = 1254;    
break;
 
 1212         case 203: nCP = 1253;    
break;
 
 1213         case 204: nCP = 1257;    
break;
 
 1219         return QStringLiteral( 
"CP%1" ).arg( nCP );
 
 1231   char **papszStyleString = CSLTokenizeString2( 
string.toUtf8().constData(), 
";",
 
 1233                             | CSLT_PRESERVEQUOTES
 
 1234                             | CSLT_PRESERVEESCAPES );
 
 1235   for ( 
int i = 0; papszStyleString[i] != 
nullptr; ++i )
 
 1241     const thread_local QRegularExpression sToolPartRx( QStringLiteral( 
"^(.*?)\\((.*)\\)$" ) );
 
 1242     const QString stylePart( papszStyleString[i] );
 
 1243     const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
 
 1244     if ( !match.hasMatch() )
 
 1247     const QString tool = match.captured( 1 );
 
 1248     const QString params = match.captured( 2 );
 
 1250     char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(), 
",", CSLT_HONOURSTRINGS
 
 1251                          | CSLT_PRESERVEESCAPES );
 
 1253     QVariantMap toolParts;
 
 1254     const thread_local QRegularExpression sToolParamRx( QStringLiteral( 
"^(.*?):(.*)$" ) );
 
 1255     for ( 
int j = 0; papszTokens[j] != 
nullptr; ++j )
 
 1257       const QString toolPart( papszTokens[j] );
 
 1258       const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
 
 1259       if ( !match.hasMatch() )
 
 1263       toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
 
 1265     CSLDestroy( papszTokens );
 
 1268     styles.insert( tool.toLower(), toolParts );
 
 1270   CSLDestroy( papszStyleString );
 
 1276   const QVariantMap styles = parseStyleString( 
string );
 
 1280     const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
 
 1281     const QRegularExpressionMatch match = sUnitRx.match( size );
 
 1282     if ( match.hasMatch() )
 
 1284       value = match.captured( 1 ).toDouble();
 
 1285       const QString unitString = match.captured( 2 );
 
 1286       if ( unitString.compare( QLatin1String( 
"px" ), Qt::CaseInsensitive ) == 0 )
 
 1290         static constexpr 
double PT_TO_INCHES_FACTOR = 1 / 72.0;
 
 1291         static constexpr 
double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
 
 1293         value *= PX_TO_PT_FACTOR;
 
 1296       else if ( unitString.compare( QLatin1String( 
"pt" ), Qt::CaseInsensitive ) == 0 )
 
 1301       else if ( unitString.compare( QLatin1String( 
"mm" ), Qt::CaseInsensitive ) == 0 )
 
 1306       else if ( unitString.compare( QLatin1String( 
"cm" ), Qt::CaseInsensitive ) == 0 )
 
 1312       else if ( unitString.compare( QLatin1String( 
"in" ), Qt::CaseInsensitive ) == 0 )
 
 1317       else if ( unitString.compare( QLatin1String( 
"g" ), Qt::CaseInsensitive ) == 0 )
 
 1322       QgsDebugMsg( QStringLiteral( 
"Unknown unit %1" ).arg( unitString ) );
 
 1326       QgsDebugMsg( QStringLiteral( 
"Could not parse style size %1" ).arg( size ) );
 
 1331   auto convertColor = []( 
const QString & string ) -> QColor
 
 1333     if ( 
string.isEmpty() )
 
 1336     const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral( 
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
 
 1337     const QRegularExpressionMatch match = sColorWithAlphaRx.match( 
string );
 
 1338     if ( match.hasMatch() )
 
 1341       return QColor( QStringLiteral( 
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
 
 1345       return QColor( 
string );
 
 1349   auto convertPen = [&convertColor, &convertSize, string]( 
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
 
 1351     QColor color = convertColor( lineStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1355     convertSize( lineStyle.value( QStringLiteral( 
"w" ) ).toString(), lineWidth, lineWidthUnit );
 
 1358     const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-pen-(\\d+)" ) );
 
 1359     const QRegularExpressionMatch match = sMapInfoId.match( 
string );
 
 1360     if ( match.hasMatch() )
 
 1362       const int penId = match.captured( 1 ).toInt();
 
 1369     std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
 
 1370     simpleLine->setWidthUnit( lineWidthUnit );
 
 1373     const QString pattern = lineStyle.value( QStringLiteral( 
"p" ) ).toString();
 
 1374     if ( !pattern.isEmpty() )
 
 1376       const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral( 
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
 
 1377       const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
 
 1378       if ( match.hasMatch() )
 
 1380         const QStringList patternValues = match.captured( 1 ).split( 
' ' );
 
 1381         QVector< qreal > dashPattern;
 
 1383         for ( 
const QString &val : patternValues )
 
 1386           convertSize( val + match.captured( 2 ), length, patternUnits );
 
 1387           dashPattern.push_back( length * lineWidth * 2 );
 
 1390         simpleLine->setCustomDashVector( dashPattern );
 
 1391         simpleLine->setCustomDashPatternUnit( patternUnits );
 
 1392         simpleLine->setUseCustomDashPattern( 
true );
 
 1396     Qt::PenCapStyle capStyle = Qt::FlatCap;
 
 1397     Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
 
 1399     const QString 
id = lineStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1400     if ( 
id.contains( QLatin1String( 
"mapinfo-pen" ), Qt::CaseInsensitive ) )
 
 1405       capStyle = Qt::RoundCap;
 
 1406       joinStyle = Qt::RoundJoin;
 
 1410     const QString penCap = lineStyle.value( QStringLiteral( 
"cap" ) ).toString();
 
 1411     if ( penCap.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1413       capStyle = Qt::FlatCap;
 
 1415     else if ( penCap.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1417       capStyle = Qt::RoundCap;
 
 1419     else if ( penCap.compare( QLatin1String( 
"p" ), Qt::CaseInsensitive ) == 0 )
 
 1421       capStyle = Qt::SquareCap;
 
 1423     simpleLine->setPenCapStyle( capStyle );
 
 1426     const QString penJoin = lineStyle.value( QStringLiteral( 
"j" ) ).toString();
 
 1427     if ( penJoin.compare( QLatin1String( 
"m" ), Qt::CaseInsensitive ) == 0 )
 
 1429       joinStyle = Qt::MiterJoin;
 
 1431     else if ( penJoin.compare( QLatin1String( 
"r" ), Qt::CaseInsensitive ) == 0 )
 
 1433       joinStyle = Qt::RoundJoin;
 
 1435     else if ( penJoin.compare( QLatin1String( 
"b" ), Qt::CaseInsensitive ) == 0 )
 
 1437       joinStyle = Qt::BevelJoin;
 
 1439     simpleLine->setPenJoinStyle( joinStyle );
 
 1441     const QString priority = lineStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1442     if ( !priority.isEmpty() )
 
 1444       simpleLine->setRenderingPass( priority.toInt() );
 
 1446     return std::make_unique< QgsLineSymbol >( 
QgsSymbolLayerList() << simpleLine.release() );
 
 1449   auto convertBrush = [&convertColor]( 
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
 
 1451     const QColor foreColor = convertColor( brushStyle.value( QStringLiteral( 
"fc" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1452     const QColor backColor = convertColor( brushStyle.value( QStringLiteral( 
"bc" ), QString() ).toString() );
 
 1454     const QString 
id = brushStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1457     const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-brush-(\\d+)" ) );
 
 1458     const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1459     if ( match.hasMatch() )
 
 1461       const int brushId = match.captured( 1 ).toInt();
 
 1468     const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-brush-(\\d+)" ) );
 
 1469     const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1471     Qt::BrushStyle style = Qt::SolidPattern;
 
 1472     if ( ogrMatch.hasMatch() )
 
 1474       const int brushId = ogrMatch.captured( 1 ).toInt();
 
 1478           style = Qt::SolidPattern;
 
 1482           style = Qt::NoBrush;
 
 1486           style = Qt::HorPattern;
 
 1490           style = Qt::VerPattern;
 
 1494           style = Qt::FDiagPattern;
 
 1498           style = Qt::BDiagPattern;
 
 1502           style = Qt::CrossPattern;
 
 1506           style = Qt::DiagCrossPattern;
 
 1512     if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
 
 1514       std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
 
 1515       backgroundFill->setLocked( 
true );
 
 1516       backgroundFill->setStrokeStyle( Qt::NoPen );
 
 1517       layers << backgroundFill.release();
 
 1520     std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
 
 1521     foregroundFill->setBrushStyle( style );
 
 1522     foregroundFill->setStrokeStyle( Qt::NoPen );
 
 1524     const QString priority = brushStyle.value( QStringLiteral( 
"l" ) ).toString();
 
 1525     if ( !priority.isEmpty() )
 
 1527       foregroundFill->setRenderingPass( priority.toInt() );
 
 1529     layers << foregroundFill.release();
 
 1530     return std::make_unique< QgsFillSymbol >( layers );
 
 1533   auto convertSymbol = [&convertColor, &convertSize, string]( 
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
 
 1535     const QColor color = convertColor( symbolStyle.value( QStringLiteral( 
"c" ), QStringLiteral( 
"#000000" ) ).toString() );
 
 1539     convertSize( symbolStyle.value( QStringLiteral( 
"s" ) ).toString(), symbolSize, symbolSizeUnit );
 
 1541     const double angle = symbolStyle.value( QStringLiteral( 
"a" ), QStringLiteral( 
"0" ) ).toDouble();
 
 1543     const QString 
id = symbolStyle.value( QStringLiteral( 
"id" ) ).toString();
 
 1546     const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral( 
"mapinfo-sym-(\\d+)" ) );
 
 1547     const QRegularExpressionMatch match = sMapInfoId.match( 
id );
 
 1548     if ( match.hasMatch() )
 
 1550       const int symbolId = match.captured( 1 ).toInt();
 
 1561     std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
 
 1563     const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral( 
"font-sym-(\\d+)" ) );
 
 1564     const QRegularExpressionMatch fontMatch = sFontId.match( 
id );
 
 1565     if ( fontMatch.hasMatch() )
 
 1567       const int symId = fontMatch.captured( 1 ).toInt();
 
 1568       const QStringList families = symbolStyle.value( QStringLiteral( 
"f" ), QString() ).toString().split( 
',' );
 
 1570       bool familyFound = 
false;
 
 1572       for ( 
const QString &family : std::as_const( families ) )
 
 1577           fontFamily = family;
 
 1584         std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
 
 1585         fontMarker->setSizeUnit( symbolSizeUnit );
 
 1586         fontMarker->setAngle( -
angle );
 
 1588         fontMarker->setColor( color );
 
 1590         const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1591         if ( strokeColor.isValid() )
 
 1593           fontMarker->setStrokeColor( strokeColor );
 
 1594           fontMarker->setStrokeWidth( 1 );
 
 1599           fontMarker->setStrokeWidth( 0 );
 
 1602         markerLayer = std::move( fontMarker );
 
 1604       else if ( !families.empty() )
 
 1613       const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral( 
"ogr-sym-(\\d+)" ) );
 
 1614       const QRegularExpressionMatch ogrMatch = sOgrId.match( 
id );
 
 1617       bool isFilled = 
true;
 
 1618       if ( ogrMatch.hasMatch() )
 
 1620         const int symId = ogrMatch.captured( 1 ).toInt();
 
 1683       std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -
angle );
 
 1684       simpleMarker->setSizeUnit( symbolSizeUnit );
 
 1688         simpleMarker->setColor( color );
 
 1689         simpleMarker->setStrokeStyle( Qt::NoPen );
 
 1693         simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
 
 1694         simpleMarker->setStrokeColor( color );
 
 1697       const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral( 
"o" ), QString() ).toString() );
 
 1698       if ( strokeColor.isValid() )
 
 1700         simpleMarker->setStrokeColor( strokeColor );
 
 1701         simpleMarker->setStrokeStyle( Qt::SolidLine );
 
 1704       markerLayer = std::move( simpleMarker );
 
 1707     return std::make_unique< QgsMarkerSymbol >( 
QgsSymbolLayerList() << markerLayer.release() );
 
 1713       if ( styles.contains( QStringLiteral( 
"symbol" ) ) )
 
 1715         const QVariantMap symbolStyle = styles.value( QStringLiteral( 
"symbol" ) ).toMap();
 
 1716         return convertSymbol( symbolStyle );
 
 1724       if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1727         const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1728         return convertPen( lineStyle );
 
 1737       std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
 
 1738       if ( styles.contains( QStringLiteral( 
"brush" ) ) )
 
 1740         const QVariantMap brushStyle = styles.value( QStringLiteral( 
"brush" ) ).toMap();
 
 1741         fillSymbol = convertBrush( brushStyle );
 
 1745         std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
 
 1746         emptyFill->setBrushStyle( Qt::NoBrush );
 
 1747         fillSymbol = std::make_unique< QgsFillSymbol >( 
QgsSymbolLayerList() << emptyFill.release() );
 
 1750       std::unique_ptr< QgsSymbol > penSymbol;
 
 1751       if ( styles.contains( QStringLiteral( 
"pen" ) ) )
 
 1753         const QVariantMap lineStyle = styles.value( QStringLiteral( 
"pen" ) ).toMap();
 
 1754         penSymbol = convertPen( lineStyle );
 
 1759         const int count = penSymbol->symbolLayerCount();
 
 1769         for ( 
int i = 0; i < count; ++i )
 
 1771           std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
 
 1772           layer->setLocked( 
true );
 
 1773           fillSymbol->appendSymbolLayer( layer.release() );
 
MarkerShape
Marker shapes.
 
@ Cross2
Rotated cross (lines only), 'x' shape.
 
@ Cross
Cross (lines only)
 
static endian_t endian()
Returns whether this machine uses big or little endian.
 
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.
 
void setCoordinateEpoch(double epoch)
Sets the coordinate epoch, as a decimal year.
 
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
 
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.
 
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
 
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
 
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.
 
Encapsulate a field in an attribute table or data source.
 
QVariant::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, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
 
int count() const
Returns number of items.
 
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
 
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.
 
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 QgsLineSymbol * convertLineSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, double size, QgsUnitTypes::RenderUnit sizeUnit, bool interleaved=false)
Converts the MapInfo line symbol with the specified identifier to a QgsLineSymbol.
 
static QgsMarkerSymbol * convertMarkerSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &color, double size, QgsUnitTypes::RenderUnit sizeUnit)
Converts the MapInfo marker symbol with the specified identifier to a QgsMarkerSymbol.
 
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 bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
 
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 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 QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
 
static QgsWkbTypes::Type ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
 
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 QVariantMap parseStyleString(const QString &string)
Parses an OGR style string to a variant map containing the style string components.
 
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
 
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...
 
RenderUnit
Rendering size units.
 
@ RenderPoints
Points (e.g., for font sizes)
 
@ RenderMillimeters
Millimeters.
 
@ RenderMapUnits
Map units.
 
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
 
Type
The WKB type describes the number of dimensions a geometry has.
 
static Type zmType(Type type, bool hasZ, bool hasM) SIP_HOLDGIL
Returns the modified input geometry type according to hasZ / hasM.
 
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
 
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
 
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
 
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.
 
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 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
 
const QgsCoordinateReferenceSystem & crs
 
void CORE_EXPORT operator()(GDALDatasetH datasource)
Destroys an gdal dataset, using the correct gdal calls.
 
void CORE_EXPORT operator()(GDALWarpOptions *options)
Destroys GDAL warp options, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRDataSourceH source)
Destroys an OGR data source, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRFeatureH feature)
Destroys an OGR feature, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRFieldDefnH definition)
Destroys an OGR field definition, using the correct gdal calls.
 
void CORE_EXPORT operator()(OGRGeometryH geometry)
Destroys an OGR geometry, using the correct gdal calls.