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