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 );
@ GeometryWeighted
New values are computed as the weighted average of the source values.
@ DefaultValue
Use default field value.
@ GeometryRatio
New values are computed by the ratio of their area/length compared to the area/length of the original...
@ DefaultValue
Use default field value.
@ Duplicate
Duplicate original value.
MarkerShape
Marker shapes.
@ Cross2
Rotated cross (lines only), 'x' shape.
@ Cross
Cross (lines only)
@ Coded
Coded field domain.
@ Range
Numeric range field domain (min/max)
@ Glob
Glob string pattern field domain.
static endian_t endian()
Returns whether this machine uses big or little endian.
Associates a code and a value.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
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.
Base class for field domains.
Qgis::FieldDomainMergePolicy mergePolicy() const
Returns the merge policy.
Qgis::FieldDomainSplitPolicy splitPolicy() const
Returns the split policy.
virtual Qgis::FieldDomainType type() const =0
Returns the type of field domain.
QString name() const
Returns the name of the field domain.
QVariant::Type fieldType() const
Returns the associated field type.
QString description() const
Returns the description of the field domain.
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 QVariant stringToVariant(OGRFieldType type, OGRFieldSubType subType, const QString &string)
Converts a string to a variant, using the provider OGR field type and subType to determine the most a...
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
static void variantTypeToOgrFieldType(QVariant::Type variantType, OGRFieldType &ogrType, OGRFieldSubType &ogrSubType)
Converts an QVariant type to the best matching OGR field type and sub type.
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 std::unique_ptr< OGRField > variantToOGRField(const QVariant &value)
Converts a QVariant to an OGRField value.
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 std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs(OGRSpatialReferenceH srs)
Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR srs object,...
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
static QString readShapefileEncodingFromCpg(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
static QString readShapefileEncodingFromLdid(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static std::unique_ptr< QgsSymbol > symbolFromStyleString(const QString &string, Qgis::SymbolType type)
Creates a new QgsSymbol matching an OGR style string.
static void ogrFieldTypeToQVariantType(OGRFieldType ogrType, OGRFieldSubType ogrSubType, QVariant::Type &variantType, QVariant::Type &variantSubType)
Converts an OGR field type and sub type to the best matching QVariant::Type equivalent.
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) const
Destroys an gdal dataset, using the correct gdal calls.
void CORE_EXPORT operator()(GDALWarpOptions *options) const
Destroys GDAL warp options, using the correct gdal calls.
void CORE_EXPORT operator()(OGRDataSourceH source) const
Destroys an OGR data source, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFeatureH feature) const
Destroys an OGR feature, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFieldDefnH definition) const
Destroys an OGR field definition, using the correct gdal calls.
void CORE_EXPORT operator()(OGRGeometryH geometry) const
Destroys an OGR geometry, using the correct gdal calls.