24 #include "qgsogrprovider.h"
42 #include <cpl_error.h>
43 #include <QJsonDocument>
46 #include <QTextStream>
47 #include <QDataStream>
48 #include <QRegularExpression>
50 #include "ogr_srs_api.h"
55 OGR_DS_Destroy( source );
61 OGR_G_DestroyGeometry( geometry );
66 OGR_Fld_Destroy( definition );
71 OGR_F_Destroy( feature );
88 CPLPushErrorHandler( CPLQuietErrorHandler );
89 GDALDeleteDataset( driver, path.toUtf8().constData() );
101 GDALDestroyWarpOptions( options );
106 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
112 return value->Integer;
115 return value->Integer64;
122 return QString::fromUtf8( value->String );
125 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
129 float secondsPart = 0;
130 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
131 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( 1000 * millisecondPart ) );
136 float secondsPart = 0;
137 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
138 return QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
139 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( 1000 * millisecondPart ) ) );
144 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
150 res.reserve( value->IntegerList.nCount );
151 for (
int i = 0; i < value->IntegerList.nCount; ++i )
152 res << value->IntegerList.paList[ i ];
156 case OFTInteger64List:
159 res.reserve( value->Integer64List.nCount );
160 for (
int i = 0; i < value->Integer64List.nCount; ++i )
161 res << value->Integer64List.paList[ i ];
168 res.reserve( value->RealList.nCount );
169 for (
int i = 0; i < value->RealList.nCount; ++i )
170 res << value->RealList.paList[ i ];
175 case OFTWideStringList:
178 res.reserve( value->StringList.nCount );
179 for (
int i = 0; i < value->StringList.nCount; ++i )
180 res << QString::fromUtf8( value->StringList.paList[ i ] );
189 std::unique_ptr< OGRField > res = std::make_unique< OGRField >();
191 switch ( value.type() )
193 case QVariant::Invalid:
194 OGR_RawField_SetUnset( res.get() );
197 res->Integer = value.toBool() ? 1 : 0;
200 res->Integer = value.toInt();
202 case QVariant::LongLong:
203 res->Integer64 = value.toLongLong();
205 case QVariant::Double:
206 res->Real = value.toDouble();
209 case QVariant::String:
210 res->String = CPLStrdup( value.toString().toUtf8().constData() );
214 const QDate date = value.toDate();
215 res->Date.Day = date.day();
216 res->Date.Month = date.month();
217 res->Date.Year = date.year();
218 res->Date.TZFlag = 0;
223 const QTime time = value.toTime();
224 res->Date.Hour = time.hour();
225 res->Date.Minute = time.minute();
226 res->Date.Second = time.second() +
static_cast< double >( time.msec() ) / 1000;
227 res->Date.TZFlag = 0;
230 case QVariant::DateTime:
232 const QDateTime dateTime = value.toDateTime();
233 res->Date.Day = dateTime.date().day();
234 res->Date.Month = dateTime.date().month();
235 res->Date.Year = dateTime.date().year();
236 res->Date.Hour = dateTime.time().hour();
237 res->Date.Minute = dateTime.time().minute();
238 res->Date.Second = dateTime.time().second() +
static_cast< double >( dateTime.time().msec() ) / 1000;
239 res->Date.TZFlag = 0;
244 QgsDebugMsg(
"Unhandled variant type in variantToOGRField" );
245 OGR_RawField_SetUnset( res.get() );
261 feature.
setId( OGR_F_GetFID( ogrFet ) );
264 if ( !readOgrFeatureGeometry( ogrFet, feature ) )
269 if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
284 int fieldCount = OGR_F_GetFieldCount( ogrFet );
285 for (
int i = 0; i < fieldCount; ++i )
287 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
294 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
295 QVariant::Type varType;
296 switch ( OGR_Fld_GetType( fldDef ) )
299 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
300 varType = QVariant::Bool;
302 varType = QVariant::Int;
305 varType = QVariant::LongLong;
308 varType = QVariant::Double;
311 varType = QVariant::Date;
314 varType = QVariant::Time;
317 varType = QVariant::DateTime;
320 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
321 varType = QVariant::Map;
323 varType = QVariant::String;
326 varType = QVariant::String;
336 if ( attIndex < 0 || attIndex >= fields.
count() )
344 return getOgrFeatureAttribute( ogrFet,
field, attIndex, encoding, ok );
349 if ( !ogrFet || attIndex < 0 )
356 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
363 QgsDebugMsg( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
372 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
376 case QVariant::String:
379 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
381 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
386 if ( value.isNull() )
387 value = QVariant( QStringLiteral(
"" ) );
393 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
396 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
398 case QVariant::LongLong:
399 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
401 case QVariant::Double:
402 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
405 case QVariant::DateTime:
408 int year, month, day, hour, minute, tzf;
410 float secondsPart = 0;
412 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
413 float millisecondPart = std::modf( second, &secondsPart );
416 value = QDate( year, month, day );
417 else if (
field.
type() == QVariant::Time )
418 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( 1000 * millisecondPart ) );
420 value = QDateTime( QDate( year, month, day ),
421 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( 1000 * millisecondPart ) ) );
425 case QVariant::ByteArray:
428 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
432 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
439 case QVariant::StringList:
442 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
443 const int count = CSLCount( lst );
446 list.reserve( count );
447 for (
int i = 0; i < count; i++ )
450 list << encoding->toUnicode( lst[i] );
452 list << QString::fromUtf8( lst[i] );
463 case QVariant::String:
466 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
467 const int count = CSLCount( lst );
470 list.reserve( count );
471 for (
int i = 0; i < count; i++ )
474 list << encoding->toUnicode( lst[i] );
476 list << QString::fromUtf8( lst[i] );
487 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
490 list.reserve( count );
491 for (
int i = 0; i < count; i++ )
500 case QVariant::Double:
504 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
507 list.reserve( count );
508 for (
int i = 0; i < count; i++ )
517 case QVariant::LongLong:
521 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
524 list.reserve( count );
525 for (
int i = 0; i < count; i++ )
536 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
550 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
552 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
556 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
579 for (
int idx = 0; idx < fields.
count(); ++idx )
581 QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
595 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
599 feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
609 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
610 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
615 std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
617 const int count = OGR_G_GetGeometryCount( geom );
618 mp->reserve( count );
619 for (
int i = 0; i < count; ++i )
631 int count = OGR_G_GetPointCount( geom );
632 QVector< double > x( count );
633 QVector< double > y( count );
635 double *pz =
nullptr;
641 double *pm =
nullptr;
648 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
655 std::unique_ptr< QgsMultiLineString > mp = std::make_unique< QgsMultiLineString >();
657 const int count = OGR_G_GetGeometryCount( geom );
658 mp->reserve( count );
659 for (
int i = 0; i < count; ++i )
669 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
671 const int count = OGR_G_GetGeometryCount( geom );
677 for (
int i = 1; i < count; ++i )
687 std::unique_ptr< QgsMultiPolygon > polygon = std::make_unique< QgsMultiPolygon >();
689 const int count = OGR_G_GetGeometryCount( geom );
690 polygon->reserve( count );
691 for (
int i = 0; i < count; ++i )
701 switch ( ogrGeomType )
703 case wkbUnknown:
return QgsWkbTypes::Type::Unknown;
704 case wkbPoint:
return QgsWkbTypes::Type::Point;
705 case wkbLineString:
return QgsWkbTypes::Type::LineString;
706 case wkbPolygon:
return QgsWkbTypes::Type::Polygon;
707 case wkbMultiPoint:
return QgsWkbTypes::Type::MultiPoint;
708 case wkbMultiLineString:
return QgsWkbTypes::Type::MultiLineString;
709 case wkbMultiPolygon:
return QgsWkbTypes::Type::MultiPolygon;
710 case wkbGeometryCollection:
return QgsWkbTypes::Type::GeometryCollection;
711 case wkbCircularString:
return QgsWkbTypes::Type::CircularString;
712 case wkbCompoundCurve:
return QgsWkbTypes::Type::CompoundCurve;
713 case wkbCurvePolygon:
return QgsWkbTypes::Type::CurvePolygon;
714 case wkbMultiCurve:
return QgsWkbTypes::Type::MultiCurve;
715 case wkbMultiSurface:
return QgsWkbTypes::Type::MultiSurface;
716 case wkbCurve:
return QgsWkbTypes::Type::Unknown;
717 case wkbSurface:
return QgsWkbTypes::Type::Unknown;
718 case wkbPolyhedralSurface:
return QgsWkbTypes::Type::Unknown;
719 case wkbTIN:
return QgsWkbTypes::Type::Unknown;
720 case wkbTriangle:
return QgsWkbTypes::Type::Triangle;
722 case wkbNone:
return QgsWkbTypes::Type::NoGeometry;
723 case wkbLinearRing:
return QgsWkbTypes::Type::LineString;
725 case wkbCircularStringZ:
return QgsWkbTypes::Type::CircularStringZ;
726 case wkbCompoundCurveZ:
return QgsWkbTypes::Type::CompoundCurveZ;
727 case wkbCurvePolygonZ:
return QgsWkbTypes::Type::CurvePolygonZ;
728 case wkbMultiCurveZ:
return QgsWkbTypes::Type::MultiCurveZ;
729 case wkbMultiSurfaceZ:
return QgsWkbTypes::Type::MultiSurfaceZ;
730 case wkbCurveZ:
return QgsWkbTypes::Type::Unknown;
731 case wkbSurfaceZ:
return QgsWkbTypes::Type::Unknown;
732 case wkbPolyhedralSurfaceZ:
return QgsWkbTypes::Type::Unknown;
733 case wkbTINZ:
return QgsWkbTypes::Type::Unknown;
734 case wkbTriangleZ:
return QgsWkbTypes::Type::TriangleZ;
736 case wkbPointM:
return QgsWkbTypes::Type::PointM;
737 case wkbLineStringM:
return QgsWkbTypes::Type::LineStringM;
738 case wkbPolygonM:
return QgsWkbTypes::Type::PolygonM;
739 case wkbMultiPointM:
return QgsWkbTypes::Type::MultiPointM;
740 case wkbMultiLineStringM:
return QgsWkbTypes::Type::MultiLineStringM;
741 case wkbMultiPolygonM:
return QgsWkbTypes::Type::MultiPolygonM;
742 case wkbGeometryCollectionM:
return QgsWkbTypes::Type::GeometryCollectionM;
743 case wkbCircularStringM:
return QgsWkbTypes::Type::CircularStringM;
744 case wkbCompoundCurveM:
return QgsWkbTypes::Type::CompoundCurveM;
745 case wkbCurvePolygonM:
return QgsWkbTypes::Type::CurvePolygonM;
746 case wkbMultiCurveM:
return QgsWkbTypes::Type::MultiCurveM;
747 case wkbMultiSurfaceM:
return QgsWkbTypes::Type::MultiSurfaceM;
748 case wkbCurveM:
return QgsWkbTypes::Type::Unknown;
749 case wkbSurfaceM:
return QgsWkbTypes::Type::Unknown;
750 case wkbPolyhedralSurfaceM:
return QgsWkbTypes::Type::Unknown;
751 case wkbTINM:
return QgsWkbTypes::Type::Unknown;
752 case wkbTriangleM:
return QgsWkbTypes::Type::TriangleM;
754 case wkbPointZM:
return QgsWkbTypes::Type::PointZM;
755 case wkbLineStringZM:
return QgsWkbTypes::Type::LineStringZM;
756 case wkbPolygonZM:
return QgsWkbTypes::Type::PolygonZM;
757 case wkbMultiPointZM:
return QgsWkbTypes::Type::MultiPointZM;
758 case wkbMultiLineStringZM:
return QgsWkbTypes::Type::MultiLineStringZM;
759 case wkbMultiPolygonZM:
return QgsWkbTypes::Type::MultiPolygonZM;
760 case wkbGeometryCollectionZM:
return QgsWkbTypes::Type::GeometryCollectionZM;
761 case wkbCircularStringZM:
return QgsWkbTypes::Type::CircularStringZM;
762 case wkbCompoundCurveZM:
return QgsWkbTypes::Type::CompoundCurveZM;
763 case wkbCurvePolygonZM:
return QgsWkbTypes::Type::CurvePolygonZM;
764 case wkbMultiCurveZM:
return QgsWkbTypes::Type::MultiCurveZM;
765 case wkbMultiSurfaceZM:
return QgsWkbTypes::Type::MultiSurfaceZM;
766 case wkbCurveZM:
return QgsWkbTypes::Type::Unknown;
767 case wkbSurfaceZM:
return QgsWkbTypes::Type::Unknown;
768 case wkbPolyhedralSurfaceZM:
return QgsWkbTypes::Type::Unknown;
769 case wkbTINZM:
return QgsWkbTypes::Type::Unknown;
770 case wkbTriangleZM:
return QgsWkbTypes::Type::TriangleZM;
772 case wkbPoint25D:
return QgsWkbTypes::Type::PointZ;
773 case wkbLineString25D:
return QgsWkbTypes::Type::LineStringZ;
774 case wkbPolygon25D:
return QgsWkbTypes::Type::PolygonZ;
775 case wkbMultiPoint25D:
return QgsWkbTypes::Type::MultiPointZ;
776 case wkbMultiLineString25D:
return QgsWkbTypes::Type::MultiLineStringZ;
777 case wkbMultiPolygon25D:
return QgsWkbTypes::Type::MultiPolygonZ;
778 case wkbGeometryCollection25D:
return QgsWkbTypes::Type::GeometryCollectionZ;
782 return QgsWkbTypes::Type::Unknown;
790 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
833 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
836 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
837 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
839 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
840 auto ret = ogrGeometryToQgsGeometry( newGeom );
841 OGR_G_DestroyGeometry( newGeom );
847 int memorySize = OGR_G_WkbSize( geom );
848 unsigned char *wkb =
new unsigned char[memorySize];
852 uint32_t origGeomType;
853 memcpy( &origGeomType, wkb + 1,
sizeof( uint32_t ) );
854 bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
855 bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
858 if ( origGeomType % 1000 == 16 )
861 int nDims = 2 + hasZ + hasM;
864 unsigned char *wkbptr = wkb;
870 memcpy( wkbptr, &newMultiType,
sizeof( uint32_t ) );
875 memcpy( &numGeoms, wkb + 5,
sizeof( uint32_t ) );
879 for ( uint32_t i = 0; i < numGeoms; ++i )
885 memcpy( wkbptr, &newSingleType,
sizeof( uint32_t ) );
886 wkbptr +=
sizeof( uint32_t );
890 memcpy( &nRings, wkbptr,
sizeof( uint32_t ) );
891 wkbptr +=
sizeof( uint32_t );
893 for ( uint32_t j = 0; j < nRings; ++j )
896 memcpy( &nPoints, wkbptr,
sizeof( uint32_t ) );
897 wkbptr +=
sizeof( uint32_t ) +
sizeof(
double ) * nDims * nPoints;
901 else if ( origGeomType % 1000 == 15 )
906 memcpy( wkb + 1, &newType,
sizeof( uint32_t ) );
917 if (
string.isEmpty() )
920 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
923 QByteArray ba =
string.toUtf8();
924 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
925 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
930 VSIUnlink( randomFileName.toUtf8().constData() );
934 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
938 VSIUnlink( randomFileName.toUtf8().constData() );
943 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
945 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
951 VSIUnlink( randomFileName.toUtf8().constData() );
959 if (
string.isEmpty() )
962 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
965 QByteArray ba =
string.toUtf8();
966 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
967 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
972 VSIUnlink( randomFileName.toUtf8().constData() );
976 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
980 VSIUnlink( randomFileName.toUtf8().constData() );
986 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
988 fields = readOgrFields( oFeat.get(), encoding );
992 VSIUnlink( randomFileName.toUtf8().constData() );
1001 for (
qgssize i = 0; stringList[i]; ++i )
1003 strings.append( QString::fromUtf8( stringList[i] ) );
1014 char *pszWkt =
nullptr;
1015 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=NO" ).toLocal8Bit();
1016 const QByteArray formatOption = QStringLiteral(
"FORMAT=WKT2" ).toLocal8Bit();
1017 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1018 OSRExportToWktEx( srs, &pszWkt, options );
1020 const QString res( pszWkt );
1027 const QString wkt = OGRSpatialReferenceToWkt( srs );
1028 if ( wkt.isEmpty() )
1031 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1032 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1034 if ( authorityName && authorityCode )
1036 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1039 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1040 OSRIsSame( srs, ogrSrsTmp ) )
1045 OSRDestroySpatialReference( ogrSrsTmp );
1050 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1051 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1052 if ( coordinateEpoch > 0 )
1070 if ( !authId.isEmpty() )
1072 ogrSrs = OSRNewSpatialReference(
nullptr );
1073 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1077 if ( ogrSrsFromWkt )
1079 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1081 OSRDestroySpatialReference( ogrSrs );
1082 ogrSrs = ogrSrsFromWkt;
1086 OSRDestroySpatialReference( ogrSrsFromWkt );
1092 OSRDestroySpatialReference( ogrSrs );
1098 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1102 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1103 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1118 const QString cpgEncoding = readShapefileEncodingFromCpg( path );
1119 if ( !cpgEncoding.isEmpty() )
1122 return readShapefileEncodingFromLdid( path );
1127 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1129 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1130 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_CPG" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1132 if ( !QFileInfo::exists( path ) )
1136 const QFileInfo fi( path );
1137 const QString baseName = fi.completeBaseName();
1138 const QString cpgPath = fi.dir().filePath( QStringLiteral(
"%1.%2" ).arg( baseName, fi.suffix() == QLatin1String(
"SHP" ) ? QStringLiteral(
"CPG" ) : QStringLiteral(
"cpg" ) ) );
1139 if ( QFile::exists( cpgPath ) )
1141 QFile cpgFile( cpgPath );
1142 if ( cpgFile.open( QIODevice::ReadOnly ) )
1144 QTextStream cpgStream( &cpgFile );
1145 const QString cpgString = cpgStream.readLine();
1148 if ( !cpgString.isEmpty() )
1153 int cpgCodePage = cpgString.toInt( &ok );
1154 if ( ok && ( ( cpgCodePage >= 437 && cpgCodePage <= 950 )
1155 || ( cpgCodePage >= 1250 && cpgCodePage <= 1258 ) ) )
1157 return QStringLiteral(
"CP%1" ).arg( cpgCodePage );
1159 else if ( cpgString.startsWith( QLatin1String(
"8859" ) ) )
1161 if ( cpgString.length() > 4 && cpgString.at( 4 ) ==
'-' )
1162 return QStringLiteral(
"ISO-8859-%1" ).arg( cpgString.mid( 5 ) );
1164 return QStringLiteral(
"ISO-8859-%1" ).arg( cpgString.mid( 4 ) );
1166 else if ( cpgString.startsWith( QLatin1String(
"UTF-8" ), Qt::CaseInsensitive ) ||
1167 cpgString.startsWith( QLatin1String(
"UTF8" ), Qt::CaseInsensitive ) )
1168 return QStringLiteral(
"UTF-8" );
1169 else if ( cpgString.startsWith( QLatin1String(
"ANSI 1251" ), Qt::CaseInsensitive ) )
1170 return QStringLiteral(
"CP1251" );
1183 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,1,0)
1185 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1186 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_LDID" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1191 if ( !QFileInfo::exists( path ) )
1195 const QFileInfo fi( path );
1196 const QString baseName = fi.completeBaseName();
1199 const QString dbfPath = fi.dir().filePath( QStringLiteral(
"%1.%2" ).arg( baseName, fi.suffix() == QLatin1String(
"SHP" ) ? QStringLiteral(
"DBF" ) : QStringLiteral(
"dbf" ) ) );
1200 if ( QFile::exists( dbfPath ) )
1202 QFile dbfFile( dbfPath );
1203 if ( dbfFile.open( QIODevice::ReadOnly ) )
1206 QDataStream dbfIn( &dbfFile );
1207 dbfIn.setByteOrder( QDataStream::LittleEndian );
1217 case 1: nCP = 437;
break;
1218 case 2: nCP = 850;
break;
1219 case 3: nCP = 1252;
break;
1220 case 4: nCP = 10000;
break;
1221 case 8: nCP = 865;
break;
1222 case 10: nCP = 850;
break;
1223 case 11: nCP = 437;
break;
1224 case 13: nCP = 437;
break;
1225 case 14: nCP = 850;
break;
1226 case 15: nCP = 437;
break;
1227 case 16: nCP = 850;
break;
1228 case 17: nCP = 437;
break;
1229 case 18: nCP = 850;
break;
1230 case 19: nCP = 932;
break;
1231 case 20: nCP = 850;
break;
1232 case 21: nCP = 437;
break;
1233 case 22: nCP = 850;
break;
1234 case 23: nCP = 865;
break;
1235 case 24: nCP = 437;
break;
1236 case 25: nCP = 437;
break;
1237 case 26: nCP = 850;
break;
1238 case 27: nCP = 437;
break;
1239 case 28: nCP = 863;
break;
1240 case 29: nCP = 850;
break;
1241 case 31: nCP = 852;
break;
1242 case 34: nCP = 852;
break;
1243 case 35: nCP = 852;
break;
1244 case 36: nCP = 860;
break;
1245 case 37: nCP = 850;
break;
1246 case 38: nCP = 866;
break;
1247 case 55: nCP = 850;
break;
1248 case 64: nCP = 852;
break;
1249 case 77: nCP = 936;
break;
1250 case 78: nCP = 949;
break;
1251 case 79: nCP = 950;
break;
1252 case 80: nCP = 874;
break;
1253 case 87:
return QStringLiteral(
"ISO-8859-1" );
1254 case 88: nCP = 1252;
break;
1255 case 89: nCP = 1252;
break;
1256 case 100: nCP = 852;
break;
1257 case 101: nCP = 866;
break;
1258 case 102: nCP = 865;
break;
1259 case 103: nCP = 861;
break;
1260 case 104: nCP = 895;
break;
1261 case 105: nCP = 620;
break;
1262 case 106: nCP = 737;
break;
1263 case 107: nCP = 857;
break;
1264 case 108: nCP = 863;
break;
1265 case 120: nCP = 950;
break;
1266 case 121: nCP = 949;
break;
1267 case 122: nCP = 936;
break;
1268 case 123: nCP = 932;
break;
1269 case 124: nCP = 874;
break;
1270 case 134: nCP = 737;
break;
1271 case 135: nCP = 852;
break;
1272 case 136: nCP = 857;
break;
1273 case 150: nCP = 10007;
break;
1274 case 151: nCP = 10029;
break;
1275 case 200: nCP = 1250;
break;
1276 case 201: nCP = 1251;
break;
1277 case 202: nCP = 1254;
break;
1278 case 203: nCP = 1253;
break;
1279 case 204: nCP = 1257;
break;
1285 return QStringLiteral(
"CP%1" ).arg( nCP );
1297 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1299 | CSLT_PRESERVEQUOTES
1300 | CSLT_PRESERVEESCAPES );
1301 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1307 const thread_local QRegularExpression sToolPartRx( QStringLiteral(
"^(.*?)\\((.*)\\)$" ) );
1308 const QString stylePart( papszStyleString[i] );
1309 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1310 if ( !match.hasMatch() )
1313 const QString tool = match.captured( 1 );
1314 const QString params = match.captured( 2 );
1316 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1317 | CSLT_PRESERVEESCAPES );
1319 QVariantMap toolParts;
1320 const thread_local QRegularExpression sToolParamRx( QStringLiteral(
"^(.*?):(.*)$" ) );
1321 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1323 const QString toolPart( papszTokens[j] );
1324 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1325 if ( !match.hasMatch() )
1329 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1331 CSLDestroy( papszTokens );
1334 styles.insert( tool.toLower(), toolParts );
1336 CSLDestroy( papszStyleString );
1342 const QVariantMap styles = parseStyleString(
string );
1346 const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
1347 const QRegularExpressionMatch match = sUnitRx.match( size );
1348 if ( match.hasMatch() )
1350 value = match.captured( 1 ).toDouble();
1351 const QString unitString = match.captured( 2 );
1352 if ( unitString.compare( QLatin1String(
"px" ), Qt::CaseInsensitive ) == 0 )
1356 static constexpr
double PT_TO_INCHES_FACTOR = 1 / 72.0;
1357 static constexpr
double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1359 value *= PX_TO_PT_FACTOR;
1362 else if ( unitString.compare( QLatin1String(
"pt" ), Qt::CaseInsensitive ) == 0 )
1367 else if ( unitString.compare( QLatin1String(
"mm" ), Qt::CaseInsensitive ) == 0 )
1372 else if ( unitString.compare( QLatin1String(
"cm" ), Qt::CaseInsensitive ) == 0 )
1378 else if ( unitString.compare( QLatin1String(
"in" ), Qt::CaseInsensitive ) == 0 )
1383 else if ( unitString.compare( QLatin1String(
"g" ), Qt::CaseInsensitive ) == 0 )
1388 QgsDebugMsg( QStringLiteral(
"Unknown unit %1" ).arg( unitString ) );
1392 QgsDebugMsg( QStringLiteral(
"Could not parse style size %1" ).arg( size ) );
1397 auto convertColor = [](
const QString & string ) -> QColor
1399 if (
string.isEmpty() )
1402 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral(
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
1403 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1404 if ( match.hasMatch() )
1407 return QColor( QStringLiteral(
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
1411 return QColor(
string );
1415 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1417 QColor color = convertColor( lineStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1421 convertSize( lineStyle.value( QStringLiteral(
"w" ) ).toString(), lineWidth, lineWidthUnit );
1424 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-pen-(\\d+)" ) );
1425 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1426 if ( match.hasMatch() )
1428 const int penId = match.captured( 1 ).toInt();
1435 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1436 simpleLine->setWidthUnit( lineWidthUnit );
1439 const QString pattern = lineStyle.value( QStringLiteral(
"p" ) ).toString();
1440 if ( !pattern.isEmpty() )
1442 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
1443 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1444 if ( match.hasMatch() )
1446 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1447 QVector< qreal > dashPattern;
1449 for (
const QString &val : patternValues )
1452 convertSize( val + match.captured( 2 ), length, patternUnits );
1453 dashPattern.push_back( length * lineWidth * 2 );
1456 simpleLine->setCustomDashVector( dashPattern );
1457 simpleLine->setCustomDashPatternUnit( patternUnits );
1458 simpleLine->setUseCustomDashPattern(
true );
1462 Qt::PenCapStyle capStyle = Qt::FlatCap;
1463 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1465 const QString
id = lineStyle.value( QStringLiteral(
"id" ) ).toString();
1466 if (
id.contains( QLatin1String(
"mapinfo-pen" ), Qt::CaseInsensitive ) )
1471 capStyle = Qt::RoundCap;
1472 joinStyle = Qt::RoundJoin;
1476 const QString penCap = lineStyle.value( QStringLiteral(
"cap" ) ).toString();
1477 if ( penCap.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1479 capStyle = Qt::FlatCap;
1481 else if ( penCap.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1483 capStyle = Qt::RoundCap;
1485 else if ( penCap.compare( QLatin1String(
"p" ), Qt::CaseInsensitive ) == 0 )
1487 capStyle = Qt::SquareCap;
1489 simpleLine->setPenCapStyle( capStyle );
1492 const QString penJoin = lineStyle.value( QStringLiteral(
"j" ) ).toString();
1493 if ( penJoin.compare( QLatin1String(
"m" ), Qt::CaseInsensitive ) == 0 )
1495 joinStyle = Qt::MiterJoin;
1497 else if ( penJoin.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1499 joinStyle = Qt::RoundJoin;
1501 else if ( penJoin.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1503 joinStyle = Qt::BevelJoin;
1505 simpleLine->setPenJoinStyle( joinStyle );
1507 const QString priority = lineStyle.value( QStringLiteral(
"l" ) ).toString();
1508 if ( !priority.isEmpty() )
1510 simpleLine->setRenderingPass( priority.toInt() );
1512 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1515 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1517 const QColor foreColor = convertColor( brushStyle.value( QStringLiteral(
"fc" ), QStringLiteral(
"#000000" ) ).toString() );
1518 const QColor backColor = convertColor( brushStyle.value( QStringLiteral(
"bc" ), QString() ).toString() );
1520 const QString
id = brushStyle.value( QStringLiteral(
"id" ) ).toString();
1523 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-brush-(\\d+)" ) );
1524 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1525 if ( match.hasMatch() )
1527 const int brushId = match.captured( 1 ).toInt();
1534 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-brush-(\\d+)" ) );
1535 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1537 Qt::BrushStyle style = Qt::SolidPattern;
1538 if ( ogrMatch.hasMatch() )
1540 const int brushId = ogrMatch.captured( 1 ).toInt();
1544 style = Qt::SolidPattern;
1548 style = Qt::NoBrush;
1552 style = Qt::HorPattern;
1556 style = Qt::VerPattern;
1560 style = Qt::FDiagPattern;
1564 style = Qt::BDiagPattern;
1568 style = Qt::CrossPattern;
1572 style = Qt::DiagCrossPattern;
1578 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1580 std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1581 backgroundFill->setLocked(
true );
1582 backgroundFill->setStrokeStyle( Qt::NoPen );
1583 layers << backgroundFill.release();
1586 std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1587 foregroundFill->setBrushStyle( style );
1588 foregroundFill->setStrokeStyle( Qt::NoPen );
1590 const QString priority = brushStyle.value( QStringLiteral(
"l" ) ).toString();
1591 if ( !priority.isEmpty() )
1593 foregroundFill->setRenderingPass( priority.toInt() );
1595 layers << foregroundFill.release();
1596 return std::make_unique< QgsFillSymbol >( layers );
1599 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1601 const QColor color = convertColor( symbolStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1605 convertSize( symbolStyle.value( QStringLiteral(
"s" ) ).toString(), symbolSize, symbolSizeUnit );
1607 const double angle = symbolStyle.value( QStringLiteral(
"a" ), QStringLiteral(
"0" ) ).toDouble();
1609 const QString
id = symbolStyle.value( QStringLiteral(
"id" ) ).toString();
1612 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-sym-(\\d+)" ) );
1613 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1614 if ( match.hasMatch() )
1616 const int symbolId = match.captured( 1 ).toInt();
1627 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1629 const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral(
"font-sym-(\\d+)" ) );
1630 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1631 if ( fontMatch.hasMatch() )
1633 const int symId = fontMatch.captured( 1 ).toInt();
1634 const QStringList families = symbolStyle.value( QStringLiteral(
"f" ), QString() ).toString().split(
',' );
1636 bool familyFound =
false;
1638 for (
const QString &family : std::as_const( families ) )
1643 fontFamily = family;
1650 std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1651 fontMarker->setSizeUnit( symbolSizeUnit );
1652 fontMarker->setAngle( -
angle );
1654 fontMarker->setColor( color );
1656 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1657 if ( strokeColor.isValid() )
1659 fontMarker->setStrokeColor( strokeColor );
1660 fontMarker->setStrokeWidth( 1 );
1665 fontMarker->setStrokeWidth( 0 );
1668 markerLayer = std::move( fontMarker );
1670 else if ( !families.empty() )
1679 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-sym-(\\d+)" ) );
1680 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1683 bool isFilled =
true;
1684 if ( ogrMatch.hasMatch() )
1686 const int symId = ogrMatch.captured( 1 ).toInt();
1749 std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -
angle );
1750 simpleMarker->setSizeUnit( symbolSizeUnit );
1754 simpleMarker->setColor( color );
1755 simpleMarker->setStrokeStyle( Qt::NoPen );
1759 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1760 simpleMarker->setStrokeColor( color );
1763 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1764 if ( strokeColor.isValid() )
1766 simpleMarker->setStrokeColor( strokeColor );
1767 simpleMarker->setStrokeStyle( Qt::SolidLine );
1770 markerLayer = std::move( simpleMarker );
1773 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1779 if ( styles.contains( QStringLiteral(
"symbol" ) ) )
1781 const QVariantMap symbolStyle = styles.value( QStringLiteral(
"symbol" ) ).toMap();
1782 return convertSymbol( symbolStyle );
1790 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1793 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1794 return convertPen( lineStyle );
1803 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1804 if ( styles.contains( QStringLiteral(
"brush" ) ) )
1806 const QVariantMap brushStyle = styles.value( QStringLiteral(
"brush" ) ).toMap();
1807 fillSymbol = convertBrush( brushStyle );
1811 std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1812 emptyFill->setBrushStyle( Qt::NoBrush );
1813 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1816 std::unique_ptr< QgsSymbol > penSymbol;
1817 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1819 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1820 penSymbol = convertPen( lineStyle );
1825 const int count = penSymbol->symbolLayerCount();
1835 for (
int i = 0; i < count; ++i )
1837 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1838 layer->setLocked(
true );
1839 fillSymbol->appendSymbolLayer( layer.release() );
1855 variantType = QVariant::Type::Invalid;
1856 variantSubType = QVariant::Type::Invalid;
1861 if ( ogrSubType == OFSTBoolean )
1863 variantType = QVariant::Bool;
1864 ogrSubType = OFSTBoolean;
1867 variantType = QVariant::Int;
1870 variantType = QVariant::LongLong;
1873 variantType = QVariant::Double;
1876 variantType = QVariant::Date;
1879 variantType = QVariant::Time;
1882 variantType = QVariant::DateTime;
1886 variantType = QVariant::ByteArray;
1891 if ( ogrSubType == OFSTJSON )
1893 ogrSubType = OFSTJSON;
1894 variantType = QVariant::Map;
1895 variantSubType = QVariant::String;
1899 variantType = QVariant::String;
1904 case OFTWideStringList:
1905 variantType = QVariant::StringList;
1906 variantSubType = QVariant::String;
1909 case OFTIntegerList:
1910 variantType = QVariant::List;
1911 variantSubType = QVariant::Int;
1915 variantType = QVariant::List;
1916 variantSubType = QVariant::Double;
1919 case OFTInteger64List:
1920 variantType = QVariant::List;
1921 variantSubType = QVariant::LongLong;
1928 ogrSubType = OFSTNone;
1929 switch ( variantType )
1931 case QVariant::Bool:
1932 ogrType = OFTInteger;
1933 ogrSubType = OFSTBoolean;
1937 ogrType = OFTInteger;
1940 case QVariant::LongLong:
1941 ogrType = OFTInteger64;
1944 case QVariant::Double:
1948 case QVariant::Char:
1949 ogrType = OFTString;
1952 case QVariant::String:
1953 ogrType = OFTString;
1956 case QVariant::StringList:
1957 ogrType = OFTStringList;
1960 case QVariant::ByteArray:
1961 ogrType = OFTBinary;
1964 case QVariant::Date:
1968 case QVariant::Time:
1971 case QVariant::DateTime:
1972 ogrType = OFTDateTime;
1976 ogrType = OFTString;
1983 if (
string.isEmpty() )
1991 res =
string.toInt( &ok );
1995 res =
string.toLongLong( &ok );
1999 res =
string.toDouble( &ok );
2009 res = QDate::fromString(
string, Qt::ISODate );
2014 res = QTime::fromString(
string, Qt::ISODate );
2019 res = QDateTime::fromString(
string, Qt::ISODate );
2029 return ok ? res : QVariant();
2033 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2039 const QString name{ OGR_FldDomain_GetName( domain ) };
2040 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2042 QVariant::Type fieldType = QVariant::Type::Invalid;
2043 QVariant::Type fieldSubType = QVariant::Type::Invalid;
2044 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2045 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2046 ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
2048 std::unique_ptr< QgsFieldDomain > res;
2049 switch ( OGR_FldDomain_GetDomainType( domain ) )
2053 QList< QgsCodedValue > values;
2054 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2055 while ( codedValue && codedValue->pszCode )
2057 const QString code( codedValue->pszCode );
2062 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2063 values.append(
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
2068 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2075 bool minIsInclusive =
false;
2076 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2081 bool maxIsInclusive =
false;
2082 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2087 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2088 minValue, minIsInclusive,
2089 maxValue, maxIsInclusive );
2094 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2095 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2099 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2101 case OFDMP_DEFAULT_VALUE:
2107 case OFDMP_GEOMETRY_WEIGHTED:
2112 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2114 case OFDSP_DEFAULT_VALUE:
2117 case OFDSP_DUPLICATE:
2120 case OFDSP_GEOMETRY_RATIO:
2132 OGRFieldType domainFieldType = OFTInteger;
2133 OGRFieldSubType domainFieldSubType = OFSTNone;
2134 variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
2136 OGRFieldDomainH res =
nullptr;
2137 switch ( domain->
type() )
2141 std::vector< OGRCodedValue > enumeration;
2142 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2143 enumeration.reserve( values.size() );
2146 OGRCodedValue codedValue;
2147 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2148 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2149 enumeration.push_back( codedValue );
2152 last.pszCode =
nullptr;
2153 last.pszValue =
nullptr;
2154 enumeration.push_back( last );
2155 res = OGR_CodedFldDomain_Create(
2156 domain->
name().toUtf8().constData(),
2163 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2165 CPLFree( value.pszCode );
2166 CPLFree( value.pszValue );
2173 std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum() );
2174 std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum() );
2175 res = OGR_RangeFldDomain_Create(
2176 domain->
name().toUtf8().constData(),
2181 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2183 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2190 res = OGR_GlobFldDomain_Create(
2191 domain->
name().toUtf8().constData(),
2195 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2204 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2207 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2210 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2217 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2220 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2223 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );