40#include "qgsogrproviderutils.h"
42#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
52#include <QJsonDocument>
57#include <QRegularExpression>
59#include "ogr_srs_api.h"
64 OGR_DS_Destroy( source );
70 OGR_G_DestroyGeometry( geometry );
75 OGR_Fld_Destroy( definition );
80 OGR_F_Destroy( feature );
97 CPLPushErrorHandler( CPLQuietErrorHandler );
98 GDALDeleteDataset( driver, path.toUtf8().constData() );
110 GDALDestroyWarpOptions( options );
113#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
116 GDALDestroyRelationship( relationship );
120static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt,
int nTZFlag )
127 else if ( nTZFlag == 1 )
129 dt.setTimeSpec( Qt::LocalTime );
131 else if ( nTZFlag == 100 )
133 dt.setTimeSpec( Qt::UTC );
139 dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
145 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
151 return value->Integer;
154 return value->Integer64;
161 return QString::fromUtf8( value->String );
164 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
168 float secondsPart = 0;
169 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
170 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
175 float secondsPart = 0;
176 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
177 QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
178 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
179 setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
185 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
191 res.reserve( value->IntegerList.nCount );
192 for (
int i = 0; i < value->IntegerList.nCount; ++i )
193 res << value->IntegerList.paList[ i ];
197 case OFTInteger64List:
200 res.reserve( value->Integer64List.nCount );
201 for (
int i = 0; i < value->Integer64List.nCount; ++i )
202 res << value->Integer64List.paList[ i ];
209 res.reserve( value->RealList.nCount );
210 for (
int i = 0; i < value->RealList.nCount; ++i )
211 res << value->RealList.paList[ i ];
216 case OFTWideStringList:
219 res.reserve( value->StringList.nCount );
220 for (
int i = 0; i < value->StringList.nCount; ++i )
221 res << QString::fromUtf8( value->StringList.paList[ i ] );
230 if ( datetime.timeSpec() == Qt::LocalTime )
232 return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
237 std::unique_ptr< OGRField > res = std::make_unique< OGRField >();
239 switch ( value.type() )
241 case QVariant::Invalid:
242 OGR_RawField_SetUnset( res.get() );
245 res->Integer = value.toBool() ? 1 : 0;
248 res->Integer = value.toInt();
250 case QVariant::LongLong:
251 res->Integer64 = value.toLongLong();
253 case QVariant::Double:
254 res->Real = value.toDouble();
257 case QVariant::String:
258 res->String = CPLStrdup( value.toString().toUtf8().constData() );
262 const QDate date = value.toDate();
263 res->Date.Day = date.day();
264 res->Date.Month = date.month();
265 res->Date.Year = date.year();
266 res->Date.TZFlag = 0;
271 const QTime time = value.toTime();
272 res->Date.Hour = time.hour();
273 res->Date.Minute = time.minute();
274 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
275 res->Date.TZFlag = 0;
278 case QVariant::DateTime:
280 const QDateTime dt = value.toDateTime();
281 const QDate date = dt.date();
282 res->Date.Day = date.day();
283 res->Date.Month = date.month();
284 res->Date.Year =
static_cast<GInt16
>( date.year() );
285 const QTime time = dt.time();
286 res->Date.Hour = time.hour();
287 res->Date.Minute = time.minute();
288 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
289 res->Date.TZFlag = OGRTZFlagFromQt( dt );
294 QgsDebugMsg(
"Unhandled variant type in variantToOGRField" );
295 OGR_RawField_SetUnset( res.get() );
311 feature.
setId( OGR_F_GetFID( ogrFet ) );
314 if ( !readOgrFeatureGeometry( ogrFet, feature ) )
319 if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
334 int fieldCount = OGR_F_GetFieldCount( ogrFet );
335 for (
int i = 0; i < fieldCount; ++i )
337 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
344 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
345 QVariant::Type varType;
346 switch ( OGR_Fld_GetType( fldDef ) )
349 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
350 varType = QVariant::Bool;
352 varType = QVariant::Int;
355 varType = QVariant::LongLong;
358 varType = QVariant::Double;
361 varType = QVariant::Date;
364 varType = QVariant::Time;
367 varType = QVariant::DateTime;
370 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
371 varType = QVariant::Map;
373 varType = QVariant::String;
376 varType = QVariant::String;
386 if ( attIndex < 0 || attIndex >= fields.
count() )
394 return getOgrFeatureAttribute( ogrFet,
field, attIndex, encoding, ok );
399 if ( !ogrFet || attIndex < 0 )
406 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
413 QgsDebugMsg( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
422 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
426 case QVariant::String:
429 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
431 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
436 if ( value.isNull() )
437 value = QVariant( QStringLiteral(
"" ) );
443 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
446 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
448 case QVariant::LongLong:
449 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
451 case QVariant::Double:
452 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
455 case QVariant::DateTime:
458 int year, month, day, hour, minute, tzf;
460 float secondsPart = 0;
462 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
463 float millisecondPart = std::modf( second, &secondsPart );
466 value = QDate( year, month, day );
467 else if (
field.
type() == QVariant::Time )
468 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
471 QDateTime dt = QDateTime( QDate( year, month, day ),
472 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
473 setQTTimeZoneFromOGRTZFlag( dt, tzf );
479 case QVariant::ByteArray:
482 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
486 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
493 case QVariant::StringList:
496 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
497 const int count = CSLCount( lst );
500 list.reserve( count );
501 for (
int i = 0; i < count; i++ )
504 list << encoding->toUnicode( lst[i] );
506 list << QString::fromUtf8( lst[i] );
517 case QVariant::String:
520 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
521 const int count = CSLCount( lst );
524 list.reserve( count );
525 for (
int i = 0; i < count; i++ )
528 list << encoding->toUnicode( lst[i] );
530 list << QString::fromUtf8( lst[i] );
541 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
544 list.reserve( count );
545 for (
int i = 0; i < count; i++ )
554 case QVariant::Double:
558 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
561 list.reserve( count );
562 for (
int i = 0; i < count; i++ )
571 case QVariant::LongLong:
575 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
578 list.reserve( count );
579 for (
int i = 0; i < count; i++ )
590 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
604 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
606 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
610 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
633 for (
int idx = 0; idx < fields.
count(); ++idx )
635 QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
649 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
653 feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
663 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
664 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
669 std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
671 const int count = OGR_G_GetGeometryCount( geom );
672 mp->reserve( count );
673 for (
int i = 0; i < count; ++i )
685 int count = OGR_G_GetPointCount( geom );
686 QVector< double > x( count );
687 QVector< double > y( count );
689 double *pz =
nullptr;
695 double *pm =
nullptr;
702 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
709 std::unique_ptr< QgsMultiLineString > mp = std::make_unique< QgsMultiLineString >();
711 const int count = OGR_G_GetGeometryCount( geom );
712 mp->reserve( count );
713 for (
int i = 0; i < count; ++i )
723 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
725 const int count = OGR_G_GetGeometryCount( geom );
731 for (
int i = 1; i < count; ++i )
741 std::unique_ptr< QgsMultiPolygon > polygon = std::make_unique< QgsMultiPolygon >();
743 const int count = OGR_G_GetGeometryCount( geom );
744 polygon->reserve( count );
745 for (
int i = 0; i < count; ++i )
755 switch ( ogrGeomType )
844 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
845 Qgis::WkbType wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
887 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
890 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
891 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
893 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
894 auto ret = ogrGeometryToQgsGeometry( newGeom );
895 OGR_G_DestroyGeometry( newGeom );
901 int memorySize = OGR_G_WkbSize( geom );
902 unsigned char *wkb =
new unsigned char[memorySize];
906 uint32_t origGeomType;
907 memcpy( &origGeomType, wkb + 1,
sizeof( uint32_t ) );
908 bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
909 bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
912 if ( origGeomType % 1000 == 16 )
915 int nDims = 2 + hasZ + hasM;
918 unsigned char *wkbptr = wkb;
924 memcpy( wkbptr, &newMultiType,
sizeof( uint32_t ) );
929 memcpy( &numGeoms, wkb + 5,
sizeof( uint32_t ) );
933 for ( uint32_t i = 0; i < numGeoms; ++i )
939 memcpy( wkbptr, &newSingleType,
sizeof( uint32_t ) );
940 wkbptr +=
sizeof( uint32_t );
944 memcpy( &nRings, wkbptr,
sizeof( uint32_t ) );
945 wkbptr +=
sizeof( uint32_t );
947 for ( uint32_t j = 0; j < nRings; ++j )
950 memcpy( &nPoints, wkbptr,
sizeof( uint32_t ) );
951 wkbptr +=
sizeof( uint32_t ) +
sizeof(
double ) * nDims * nPoints;
955 else if ( origGeomType % 1000 == 15 )
960 memcpy( wkb + 1, &newType,
sizeof( uint32_t ) );
971 if (
string.isEmpty() )
974 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
977 QByteArray ba =
string.toUtf8();
978 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
979 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
984 VSIUnlink( randomFileName.toUtf8().constData() );
988 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
992 VSIUnlink( randomFileName.toUtf8().constData() );
997 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
999 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
1005 VSIUnlink( randomFileName.toUtf8().constData() );
1013 if (
string.isEmpty() )
1016 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1019 QByteArray ba =
string.toUtf8();
1020 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1021 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1026 VSIUnlink( randomFileName.toUtf8().constData() );
1030 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1034 VSIUnlink( randomFileName.toUtf8().constData() );
1040 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1042 fields = readOgrFields( oFeat.get(), encoding );
1046 VSIUnlink( randomFileName.toUtf8().constData() );
1055 QStringList strings;
1057 for (
qgssize i = 0; stringList[i]; ++i )
1059 strings.append( QString::fromUtf8( stringList[i] ) );
1070 char *pszWkt =
nullptr;
1071 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=NO" ).toLocal8Bit();
1072 const QByteArray formatOption = QStringLiteral(
"FORMAT=WKT2" ).toLocal8Bit();
1073 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1074 OSRExportToWktEx( srs, &pszWkt, options );
1076 const QString res( pszWkt );
1083 const QString wkt = OGRSpatialReferenceToWkt( srs );
1084 if ( wkt.isEmpty() )
1087 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1088 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1090 if ( authorityName && authorityCode )
1092 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1095 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1096 OSRIsSame( srs, ogrSrsTmp ) )
1101 OSRDestroySpatialReference( ogrSrsTmp );
1106#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1107 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1108 if ( coordinateEpoch > 0 )
1126 if ( !authId.isEmpty() )
1128 ogrSrs = OSRNewSpatialReference(
nullptr );
1129 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1133 if ( ogrSrsFromWkt )
1135 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1137 OSRDestroySpatialReference( ogrSrs );
1138 ogrSrs = ogrSrsFromWkt;
1142 OSRDestroySpatialReference( ogrSrsFromWkt );
1148 OSRDestroySpatialReference( ogrSrs );
1154 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1158 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1159#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1174 const QString cpgEncoding = readShapefileEncodingFromCpg( path );
1175 if ( !cpgEncoding.isEmpty() )
1178 return readShapefileEncodingFromLdid( path );
1184 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1185 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_CPG" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1191 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1192 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_LDID" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1199 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1201 | CSLT_PRESERVEQUOTES
1202 | CSLT_PRESERVEESCAPES );
1203 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1209 const thread_local QRegularExpression sToolPartRx( QStringLiteral(
"^(.*?)\\((.*)\\)$" ) );
1210 const QString stylePart( papszStyleString[i] );
1211 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1212 if ( !match.hasMatch() )
1215 const QString tool = match.captured( 1 );
1216 const QString params = match.captured( 2 );
1218 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1219 | CSLT_PRESERVEESCAPES );
1221 QVariantMap toolParts;
1222 const thread_local QRegularExpression sToolParamRx( QStringLiteral(
"^(.*?):(.*)$" ) );
1223 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1225 const QString toolPart( papszTokens[j] );
1226 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1227 if ( !match.hasMatch() )
1231 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1233 CSLDestroy( papszTokens );
1236 styles.insert( tool.toLower(), toolParts );
1238 CSLDestroy( papszStyleString );
1244 const QVariantMap styles = parseStyleString(
string );
1246 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1248 const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
1249 const QRegularExpressionMatch match = sUnitRx.match( size );
1250 if ( match.hasMatch() )
1252 value = match.captured( 1 ).toDouble();
1253 const QString unitString = match.captured( 2 );
1254 if ( unitString.compare( QLatin1String(
"px" ), Qt::CaseInsensitive ) == 0 )
1258 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1259 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1260 unit = Qgis::RenderUnit::Points;
1261 value *= PX_TO_PT_FACTOR;
1264 else if ( unitString.compare( QLatin1String(
"pt" ), Qt::CaseInsensitive ) == 0 )
1266 unit = Qgis::RenderUnit::Points;
1269 else if ( unitString.compare( QLatin1String(
"mm" ), Qt::CaseInsensitive ) == 0 )
1271 unit = Qgis::RenderUnit::Millimeters;
1274 else if ( unitString.compare( QLatin1String(
"cm" ), Qt::CaseInsensitive ) == 0 )
1277 unit = Qgis::RenderUnit::Millimeters;
1280 else if ( unitString.compare( QLatin1String(
"in" ), Qt::CaseInsensitive ) == 0 )
1282 unit = Qgis::RenderUnit::Inches;
1285 else if ( unitString.compare( QLatin1String(
"g" ), Qt::CaseInsensitive ) == 0 )
1287 unit = Qgis::RenderUnit::MapUnits;
1290 QgsDebugMsg( QStringLiteral(
"Unknown unit %1" ).arg( unitString ) );
1294 QgsDebugMsg( QStringLiteral(
"Could not parse style size %1" ).arg( size ) );
1299 auto convertColor = [](
const QString & string ) -> QColor
1301 if (
string.isEmpty() )
1304 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral(
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
1305 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1306 if ( match.hasMatch() )
1309 return QColor( QStringLiteral(
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
1313 return QColor(
string );
1317 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1319 QColor color = convertColor( lineStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1323 convertSize( lineStyle.value( QStringLiteral(
"w" ) ).toString(), lineWidth, lineWidthUnit );
1326 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-pen-(\\d+)" ) );
1327 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1328 if ( match.hasMatch() )
1330 const int penId = match.captured( 1 ).toInt();
1337 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1338 simpleLine->setWidthUnit( lineWidthUnit );
1341 const QString pattern = lineStyle.value( QStringLiteral(
"p" ) ).toString();
1342 if ( !pattern.isEmpty() )
1344 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
1345 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1346 if ( match.hasMatch() )
1348 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1349 QVector< qreal > dashPattern;
1351 for (
const QString &val : patternValues )
1354 convertSize( val + match.captured( 2 ), length, patternUnits );
1355 dashPattern.push_back( length * lineWidth * 2 );
1358 simpleLine->setCustomDashVector( dashPattern );
1359 simpleLine->setCustomDashPatternUnit( patternUnits );
1360 simpleLine->setUseCustomDashPattern(
true );
1364 Qt::PenCapStyle capStyle = Qt::FlatCap;
1365 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1367 const QString
id = lineStyle.value( QStringLiteral(
"id" ) ).toString();
1368 if (
id.contains( QLatin1String(
"mapinfo-pen" ), Qt::CaseInsensitive ) )
1373 capStyle = Qt::RoundCap;
1374 joinStyle = Qt::RoundJoin;
1378 const QString penCap = lineStyle.value( QStringLiteral(
"cap" ) ).toString();
1379 if ( penCap.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1381 capStyle = Qt::FlatCap;
1383 else if ( penCap.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1385 capStyle = Qt::RoundCap;
1387 else if ( penCap.compare( QLatin1String(
"p" ), Qt::CaseInsensitive ) == 0 )
1389 capStyle = Qt::SquareCap;
1391 simpleLine->setPenCapStyle( capStyle );
1394 const QString penJoin = lineStyle.value( QStringLiteral(
"j" ) ).toString();
1395 if ( penJoin.compare( QLatin1String(
"m" ), Qt::CaseInsensitive ) == 0 )
1397 joinStyle = Qt::MiterJoin;
1399 else if ( penJoin.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1401 joinStyle = Qt::RoundJoin;
1403 else if ( penJoin.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1405 joinStyle = Qt::BevelJoin;
1407 simpleLine->setPenJoinStyle( joinStyle );
1409 const QString priority = lineStyle.value( QStringLiteral(
"l" ) ).toString();
1410 if ( !priority.isEmpty() )
1412 simpleLine->setRenderingPass( priority.toInt() );
1414 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1417 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1419 const QColor foreColor = convertColor( brushStyle.value( QStringLiteral(
"fc" ), QStringLiteral(
"#000000" ) ).toString() );
1420 const QColor backColor = convertColor( brushStyle.value( QStringLiteral(
"bc" ), QString() ).toString() );
1422 const QString
id = brushStyle.value( QStringLiteral(
"id" ) ).toString();
1425 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-brush-(\\d+)" ) );
1426 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1427 if ( match.hasMatch() )
1429 const int brushId = match.captured( 1 ).toInt();
1436 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-brush-(\\d+)" ) );
1437 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1439 Qt::BrushStyle style = Qt::SolidPattern;
1440 if ( ogrMatch.hasMatch() )
1442 const int brushId = ogrMatch.captured( 1 ).toInt();
1446 style = Qt::SolidPattern;
1450 style = Qt::NoBrush;
1454 style = Qt::HorPattern;
1458 style = Qt::VerPattern;
1462 style = Qt::FDiagPattern;
1466 style = Qt::BDiagPattern;
1470 style = Qt::CrossPattern;
1474 style = Qt::DiagCrossPattern;
1480 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1482 std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1483 backgroundFill->setLocked(
true );
1484 backgroundFill->setStrokeStyle( Qt::NoPen );
1485 layers << backgroundFill.release();
1488 std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1489 foregroundFill->setBrushStyle( style );
1490 foregroundFill->setStrokeStyle( Qt::NoPen );
1492 const QString priority = brushStyle.value( QStringLiteral(
"l" ) ).toString();
1493 if ( !priority.isEmpty() )
1495 foregroundFill->setRenderingPass( priority.toInt() );
1497 layers << foregroundFill.release();
1498 return std::make_unique< QgsFillSymbol >( layers );
1501 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1503 const QColor color = convertColor( symbolStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1507 convertSize( symbolStyle.value( QStringLiteral(
"s" ) ).toString(), symbolSize, symbolSizeUnit );
1509 const double angle = symbolStyle.value( QStringLiteral(
"a" ), QStringLiteral(
"0" ) ).toDouble();
1511 const QString
id = symbolStyle.value( QStringLiteral(
"id" ) ).toString();
1514 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-sym-(\\d+)" ) );
1515 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1516 if ( match.hasMatch() )
1518 const int symbolId = match.captured( 1 ).toInt();
1529 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1531 const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral(
"font-sym-(\\d+)" ) );
1532 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1533 if ( fontMatch.hasMatch() )
1535 const int symId = fontMatch.captured( 1 ).toInt();
1536 const QStringList families = symbolStyle.value( QStringLiteral(
"f" ), QString() ).toString().split(
',' );
1538 bool familyFound =
false;
1541 for (
const QString &family : std::as_const( families ) )
1549 fontFamily = processedFamily;
1556 std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1557 fontMarker->setSizeUnit( symbolSizeUnit );
1558 fontMarker->setAngle( -
angle );
1560 fontMarker->setColor( color );
1562 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1563 if ( strokeColor.isValid() )
1565 fontMarker->setStrokeColor( strokeColor );
1566 fontMarker->setStrokeWidth( 1 );
1567 fontMarker->setStrokeWidthUnit( Qgis::RenderUnit::Points );
1571 fontMarker->setStrokeWidth( 0 );
1574 markerLayer = std::move( fontMarker );
1576 else if ( !families.empty() )
1585 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-sym-(\\d+)" ) );
1586 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1589 bool isFilled =
true;
1590 if ( ogrMatch.hasMatch() )
1592 const int symId = ogrMatch.captured( 1 ).toInt();
1655 std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -
angle );
1656 simpleMarker->setSizeUnit( symbolSizeUnit );
1660 simpleMarker->setColor( color );
1661 simpleMarker->setStrokeStyle( Qt::NoPen );
1665 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1666 simpleMarker->setStrokeColor( color );
1669 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1670 if ( strokeColor.isValid() )
1672 simpleMarker->setStrokeColor( strokeColor );
1673 simpleMarker->setStrokeStyle( Qt::SolidLine );
1676 markerLayer = std::move( simpleMarker );
1679 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1685 if ( styles.contains( QStringLiteral(
"symbol" ) ) )
1687 const QVariantMap symbolStyle = styles.value( QStringLiteral(
"symbol" ) ).toMap();
1688 return convertSymbol( symbolStyle );
1696 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1699 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1700 return convertPen( lineStyle );
1709 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1710 if ( styles.contains( QStringLiteral(
"brush" ) ) )
1712 const QVariantMap brushStyle = styles.value( QStringLiteral(
"brush" ) ).toMap();
1713 fillSymbol = convertBrush( brushStyle );
1717 std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1718 emptyFill->setBrushStyle( Qt::NoBrush );
1719 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1722 std::unique_ptr< QgsSymbol > penSymbol;
1723 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1725 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1726 penSymbol = convertPen( lineStyle );
1731 const int count = penSymbol->symbolLayerCount();
1741 for (
int i = 0; i < count; ++i )
1743 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1744 layer->setLocked(
true );
1745 fillSymbol->appendSymbolLayer( layer.release() );
1761 variantType = QVariant::Type::Invalid;
1762 variantSubType = QVariant::Type::Invalid;
1767 if ( ogrSubType == OFSTBoolean )
1769 variantType = QVariant::Bool;
1770 ogrSubType = OFSTBoolean;
1773 variantType = QVariant::Int;
1776 variantType = QVariant::LongLong;
1779 variantType = QVariant::Double;
1782 variantType = QVariant::Date;
1785 variantType = QVariant::Time;
1788 variantType = QVariant::DateTime;
1792 variantType = QVariant::ByteArray;
1797 if ( ogrSubType == OFSTJSON )
1799 ogrSubType = OFSTJSON;
1800 variantType = QVariant::Map;
1801 variantSubType = QVariant::String;
1805 variantType = QVariant::String;
1810 case OFTWideStringList:
1811 variantType = QVariant::StringList;
1812 variantSubType = QVariant::String;
1815 case OFTIntegerList:
1816 variantType = QVariant::List;
1817 variantSubType = QVariant::Int;
1821 variantType = QVariant::List;
1822 variantSubType = QVariant::Double;
1825 case OFTInteger64List:
1826 variantType = QVariant::List;
1827 variantSubType = QVariant::LongLong;
1834 ogrSubType = OFSTNone;
1835 switch ( variantType )
1837 case QVariant::Bool:
1838 ogrType = OFTInteger;
1839 ogrSubType = OFSTBoolean;
1843 ogrType = OFTInteger;
1846 case QVariant::LongLong:
1847 ogrType = OFTInteger64;
1850 case QVariant::Double:
1854 case QVariant::Char:
1855 ogrType = OFTString;
1858 case QVariant::String:
1859 ogrType = OFTString;
1862 case QVariant::StringList:
1863 ogrType = OFTStringList;
1866 case QVariant::ByteArray:
1867 ogrType = OFTBinary;
1870 case QVariant::Date:
1874 case QVariant::Time:
1877 case QVariant::DateTime:
1878 ogrType = OFTDateTime;
1882 ogrType = OFTString;
1889 if (
string.isEmpty() )
1897 res =
string.toInt( &ok );
1901 res =
string.toLongLong( &ok );
1905 res =
string.toDouble( &ok );
1915 res = QDate::fromString(
string, Qt::ISODate );
1920 res = QTime::fromString(
string, Qt::ISODate );
1925 res = QDateTime::fromString(
string, Qt::ISODate );
1935 return ok ? res : QVariant();
1943 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
1945 int nMaxIntLen = 11;
1946 int nMaxInt64Len = 21;
1947 int nMaxDoubleLen = 20;
1948 int nMaxDoublePrec = 15;
1950 if ( driverName == QLatin1String(
"GPKG" ) )
1960 QList<QgsVectorDataProvider::NativeType> nativeTypes;
1964 <<
QgsVectorDataProvider::NativeType( QObject::tr(
"Decimal number (real)" ), QStringLiteral(
"double" ), QVariant::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
1967 if ( driverName == QLatin1String(
"GPKG" ) )
1970 bool supportsDate =
true;
1971 bool supportsTime =
true;
1972 bool supportsDateTime =
true;
1973 bool supportsBinary =
false;
1974 bool supportIntegerList =
false;
1975 bool supportInteger64List =
false;
1976 bool supportRealList =
false;
1977 bool supportsStringList =
false;
1981 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
1983 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
1984 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
1985 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
1986 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
1987 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
1988 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
1989 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
1990 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
1991 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
1992 CSLDestroy( papszTokens );
1997#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
1998 if ( driverName == QLatin1String(
"ESRI Shapefile" ) )
2000 supportsDateTime =
false;
2014 if ( supportsDateTime )
2019 if ( supportsBinary )
2024 if ( supportIntegerList )
2029 if ( supportInteger64List )
2034 if ( supportRealList )
2039 if ( supportsStringList )
2045 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2046 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2057#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2063 const QString name{ OGR_FldDomain_GetName( domain ) };
2064 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2066 QVariant::Type fieldType = QVariant::Type::Invalid;
2067 QVariant::Type fieldSubType = QVariant::Type::Invalid;
2068 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2069 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2070 ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
2072 std::unique_ptr< QgsFieldDomain > res;
2073 switch ( OGR_FldDomain_GetDomainType( domain ) )
2077 QList< QgsCodedValue > values;
2078 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2079 while ( codedValue && codedValue->pszCode )
2081 const QString code( codedValue->pszCode );
2086 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2087 values.append(
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
2092 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2099 bool minIsInclusive =
false;
2100 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2105 bool maxIsInclusive =
false;
2106 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2111 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2112 minValue, minIsInclusive,
2113 maxValue, maxIsInclusive );
2118 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2119 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2123 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2125 case OFDMP_DEFAULT_VALUE:
2131 case OFDMP_GEOMETRY_WEIGHTED:
2136 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2138 case OFDSP_DEFAULT_VALUE:
2141 case OFDSP_DUPLICATE:
2144 case OFDSP_GEOMETRY_RATIO:
2156 OGRFieldType domainFieldType = OFTInteger;
2157 OGRFieldSubType domainFieldSubType = OFSTNone;
2158 variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
2160 OGRFieldDomainH res =
nullptr;
2161 switch ( domain->
type() )
2165 std::vector< OGRCodedValue > enumeration;
2166 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2167 enumeration.reserve( values.size() );
2170 OGRCodedValue codedValue;
2171 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2172 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2173 enumeration.push_back( codedValue );
2176 last.pszCode =
nullptr;
2177 last.pszValue =
nullptr;
2178 enumeration.push_back( last );
2179 res = OGR_CodedFldDomain_Create(
2180 domain->
name().toUtf8().constData(),
2187 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2189 CPLFree( value.pszCode );
2190 CPLFree( value.pszValue );
2197 std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum() );
2198 std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum() );
2199 res = OGR_RangeFldDomain_Create(
2200 domain->
name().toUtf8().constData(),
2205 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2207 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2214 res = OGR_GlobFldDomain_Create(
2215 domain->
name().toUtf8().constData(),
2219 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2228 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2231 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2234 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2241 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2244 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2247 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2260#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2264 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2266 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2268 QVariantMap leftTableUriParts = datasetUriParts;
2269 leftTableUriParts.insert( QStringLiteral(
"layerName" ), leftTableName );
2270 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2272 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2273 QVariantMap rightTableUriParts = datasetUriParts;
2274 rightTableUriParts.insert( QStringLiteral(
"layerName" ), rightTableName );
2275 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2277 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2278 QString mappingTableSource;
2279 if ( !mappingTableName.isEmpty() )
2281 QVariantMap mappingTableUriParts = datasetUriParts;
2282 mappingTableUriParts.insert( QStringLiteral(
"layerName" ), mappingTableName );
2283 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2286 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2288 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2290 CSLDestroy( cslLeftTableFieldNames );
2292 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2294 CSLDestroy( cslRightTableFieldNames );
2296 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2298 CSLDestroy( cslLeftMappingTableFieldNames );
2300 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2302 CSLDestroy( cslRightMappingTableFieldNames );
2304 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2305 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2306 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2308 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2310 switch ( relationshipType )
2316 case GRT_ASSOCIATION:
2320 case GRT_AGGREGATION:
2321 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2325 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2327 switch ( eCardinality )
2329 case GRC_ONE_TO_ONE:
2332 case GRC_ONE_TO_MANY:
2335 case GRC_MANY_TO_ONE:
2338 case GRC_MANY_TO_MANY:
2343 switch ( cardinality )
2352 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2353 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2368 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2369 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2387 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2391 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2394 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2397 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2400 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2407 const QString leftTableName = leftParts.value( QStringLiteral(
"layerName" ) ).toString();
2408 if ( leftTableName.isEmpty() )
2410 error = QObject::tr(
"Parent table name was not set" );
2415 const QString rightTableName = rightParts.value( QStringLiteral(
"layerName" ) ).toString();
2416 if ( rightTableName.isEmpty() )
2418 error = QObject::tr(
"Child table name was not set" );
2422 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != rightParts.value( QStringLiteral(
"path" ) ).toString() )
2424 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2428 QString mappingTableName;
2432 mappingTableName = mappingParts.value( QStringLiteral(
"layerName" ) ).toString();
2433 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != mappingParts.value( QStringLiteral(
"path" ) ).toString() )
2435 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2441 leftTableName.toLocal8Bit().constData(),
2442 rightTableName.toLocal8Bit().constData(),
2447 int count = leftFieldNames.count();
2448 char **lst =
new char *[count + 1];
2452 for (
const QString &
string : leftFieldNames )
2454 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2458 lst[count] =
nullptr;
2459 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2464 count = rightFieldNames.count();
2465 lst =
new char *[count + 1];
2469 for (
const QString &
string : rightFieldNames )
2471 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2475 lst[count] =
nullptr;
2476 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2479 if ( !mappingTableName.isEmpty() )
2481 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2485 int count = leftFieldNames.count();
2486 char **lst =
new char *[count + 1];
2490 for (
const QString &
string : leftFieldNames )
2492 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2496 lst[count] =
nullptr;
2497 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2502 count = rightFieldNames.count();
2503 lst =
new char *[count + 1];
2507 for (
const QString &
string : rightFieldNames )
2509 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2513 lst[count] =
nullptr;
2514 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2522 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2526 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2532 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2534 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2538 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
RelationshipStrength
Relationship strength.
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
@ GeometryWeighted
New values are computed as the weighted average of the source values.
@ DefaultValue
Use default field value.
@ GeometryRatio
New values are computed by the ratio of their area/length compared to the area/length of the original...
@ UnsetField
Clears the field value so that the data provider backend will populate using any backend triggers or ...
@ DefaultValue
Use default field value.
@ Duplicate
Duplicate original value.
MarkerShape
Marker shapes.
@ Cross2
Rotated cross (lines only), 'x' shape.
@ Cross
Cross (lines only)
RenderUnit
Rendering size units.
@ Coded
Coded field domain.
@ Range
Numeric range field domain (min/max)
@ Glob
Glob string pattern field domain.
RelationshipCardinality
Relationship cardinality.
@ ManyToMany
Many to many relationship.
@ ManyToOne
Many to one relationship.
@ OneToOne
One to one relationship.
@ OneToMany
One to many relationship.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ LineString25D
LineString25D.
@ MultiSurfaceM
MultiSurfaceM.
@ MultiLineStringZM
MultiLineStringZM.
@ MultiPointZM
MultiPointZM.
@ MultiPointZ
MultiPointZ.
@ CompoundCurve
CompoundCurve.
@ MultiPolygonZM
MultiPolygonZM.
@ LineStringM
LineStringM.
@ MultiLineStringM
MultiLineStringM.
@ MultiPointM
MultiPointM.
@ LineStringZM
LineStringZM.
@ GeometryCollectionZM
GeometryCollectionZM.
@ CompoundCurveZM
CompoundCurveZM.
@ CompoundCurveM
CompoundCurveM.
@ MultiPolygon
MultiPolygon.
@ GeometryCollectionZ
GeometryCollectionZ.
@ GeometryCollectionM
GeometryCollectionM.
@ CircularStringZM
CircularStringZM.
@ MultiSurfaceZ
MultiSurfaceZ.
@ CurvePolygonZM
CurvePolygonZM.
@ MultiLineString
MultiLineString.
@ MultiPolygonM
MultiPolygonM.
@ MultiCurveZM
MultiCurveZM.
@ MultiSurfaceZM
MultiSurfaceZM.
@ CurvePolygonM
CurvePolygonM.
@ CircularString
CircularString.
@ MultiLineStringZ
MultiLineStringZ.
@ GeometryCollection
GeometryCollection.
@ MultiPolygonZ
MultiPolygonZ.
@ CurvePolygonZ
CurvePolygonZ.
@ CompoundCurveZ
CompoundCurveZ.
@ MultiCurveZ
MultiCurveZ.
@ MultiCurveM
MultiCurveM.
@ CircularStringM
CircularStringM.
@ CurvePolygon
CurvePolygon.
@ CircularStringZ
CircularStringZ.
@ LineStringZ
LineStringZ.
@ MultiSurface
MultiSurface.
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
static endian_t endian()
Returns whether this machine uses big or little endian.
Associates a code and a value.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
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).
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
A geometry is the spatial representation of a feature.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static void warning(const QString &msg)
Goes to qWarning.
Context for a MapInfo symbol conversion operation.
static QgsFillSymbol * convertFillSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, const QColor &backColor=QColor())
Converts the MapInfo fill symbol with the specified identifier to a QgsFillSymbol.
static QgsMarkerSymbol * convertMarkerSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &color, double size, Qgis::RenderUnit sizeUnit)
Converts the MapInfo marker symbol with the specified identifier to a QgsMarkerSymbol.
static QgsLineSymbol * convertLineSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, double size, Qgis::RenderUnit sizeUnit, bool interleaved=false)
Converts the MapInfo line symbol with the specified identifier to a QgsLineSymbol.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QString readShapefileEncoding(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static QgsWeakRelation convertRelationship(GDALRelationshipH relationship, const QString &datasetUri)
Converts an GDAL relationship definition to a QgsWeakRelation equivalent.
static QVariant stringToVariant(OGRFieldType type, OGRFieldSubType subType, const QString &string)
Converts a string to a variant, using the provider OGR field type and subType to determine the most a...
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
static Qgis::WkbType ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
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 QList< QgsVectorDataProvider::NativeType > nativeFieldTypesForDriver(GDALDriverH driver)
Returns the list of native field types supported for a driver.
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs(OGRSpatialReferenceH srs)
Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR srs object,...
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
static QString readShapefileEncodingFromCpg(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
static QString readShapefileEncodingFromLdid(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static std::unique_ptr< QgsSymbol > symbolFromStyleString(const QString &string, Qgis::SymbolType type)
Creates a new QgsSymbol matching an OGR style string.
static 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 int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
static bool shapeIsFilled(Qgis::MarkerShape shape)
Returns true if a symbol shape has a fill.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QString typeToDisplayString(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns a user-friendly translated string representing a QVariant type.
The QgsWeakRelation class represent a QgsRelation with possibly unresolved layers or unmatched fields...
void setMappingTable(const QgsVectorLayerRef &table)
Sets a weak reference to the mapping table, which forms the middle table in many-to-many relationship...
QStringList mappingReferencingLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
void setForwardPathLabel(const QString &label)
Sets the label of the forward path for the relationship.
QString mappingTableSource() const
Returns the source URI for the mapping table, which forms the middle table in many-to-many relationsh...
void setMappingReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
void setBackwardPathLabel(const QString &label)
Sets the label of the backward path for the relationship.
QString relatedTableType() const
Returns the type string of the related table.
void setReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the referencingLayer() involved in the relationship.
QString name() const
Returns the relationship's name.
QString backwardPathLabel() const
Returns the label of the backward path for the relationship.
void setMappingReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
QString referencedLayerSource() const
Returns the source URI for the referenced (or "parent" / "left") layer.
QString referencingLayerSource() const
Returns the source URI for the referencing (or "child" / "right") layer.
QString forwardPathLabel() const
Returns the label of the forward path for the relationship.
Qgis::RelationshipCardinality cardinality() const
Returns the relationship's cardinality.
void setCardinality(Qgis::RelationshipCardinality cardinality)
Sets the relationship's cardinality.
QStringList referencedLayerFields() const
Returns the list of fields from the referencedLayer() involved in the relationship.
QStringList mappingReferencedLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
void setRelatedTableType(const QString &type)
Sets the type string of the related table.
QStringList referencingLayerFields() const
Returns the list of fields from the referencingLayer() involved in the relationship.
void setReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the referencedLayer() involved in the relationship.
Qgis::RelationshipStrength strength() const
Returns the strength of the relation.
static bool hasZ(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
Returns the flat type for a WKB type.
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM) SIP_HOLDGIL
Returns the modified input geometry type according to hasZ / hasM.
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.
std::unique_ptr< std::remove_pointer< GDALRelationshipH >::type, GDALRelationshipDeleter > relationship_unique_ptr
Scoped GDAL relationship.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
void * OGRSpatialReferenceH
QList< QgsFeature > QgsFeatureList
#define DEFAULT_SIMPLELINE_WIDTH
#define DEFAULT_SIMPLEMARKER_SIZE
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString(OGRGeometryH geom)
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
std::unique_ptr< QgsPolygon > ogrGeometryToQgsPolygon(OGRGeometryH geom)
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
std::unique_ptr< QgsMultiPolygon > ogrGeometryToQgsMultiPolygon(OGRGeometryH geom)
QList< QgsSymbolLayer * > QgsSymbolLayerList
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
const QgsCoordinateReferenceSystem & crs
void CORE_EXPORT operator()(GDALDatasetH datasource) const
Destroys an gdal dataset, using the correct gdal calls.
void CORE_EXPORT operator()(GDALRelationshipH relationship) const
Destroys GDAL relationship, using the correct gdal calls.
void CORE_EXPORT operator()(GDALWarpOptions *options) const
Destroys GDAL warp options, using the correct gdal calls.
void CORE_EXPORT operator()(OGRDataSourceH source) const
Destroys an OGR data source, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFeatureH feature) const
Destroys an OGR feature, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFieldDefnH definition) const
Destroys an OGR field definition, using the correct gdal calls.
void CORE_EXPORT operator()(OGRGeometryH geometry) const
Destroys an OGR geometry, using the correct gdal calls.