38#include "qgsogrproviderutils.h"
44#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
55#include <QJsonDocument>
60#include <QRegularExpression>
62#include "ogr_srs_api.h"
64#include "nlohmann/json.hpp"
68 OGR_DS_Destroy( source );
74 OGR_G_DestroyGeometry( geometry );
79 OGR_Fld_Destroy( definition );
84 OGR_F_Destroy( feature );
101 CPLPushErrorHandler( CPLQuietErrorHandler );
102 GDALDeleteDataset( driver, path.toUtf8().constData() );
103 CPLPopErrorHandler();
114 GDALDestroyWarpOptions( options );
117#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
120 GDALDestroyRelationship( relationship );
124static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt,
int nTZFlag )
131 else if ( nTZFlag == 1 )
133 dt.setTimeSpec( Qt::LocalTime );
135 else if ( nTZFlag == 100 )
137 dt.setTimeSpec( Qt::UTC );
143 dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
149 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
155 return value->Integer;
158 return value->Integer64;
165 return QString::fromUtf8( value->String );
168 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
172 float secondsPart = 0;
173 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
174 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
179 float secondsPart = 0;
180 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
181 QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
182 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
183 setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
189 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
195 res.reserve( value->IntegerList.nCount );
196 for (
int i = 0; i < value->IntegerList.nCount; ++i )
197 res << value->IntegerList.paList[ i ];
201 case OFTInteger64List:
204 res.reserve( value->Integer64List.nCount );
205 for (
int i = 0; i < value->Integer64List.nCount; ++i )
206 res << value->Integer64List.paList[ i ];
213 res.reserve( value->RealList.nCount );
214 for (
int i = 0; i < value->RealList.nCount; ++i )
215 res << value->RealList.paList[ i ];
220 case OFTWideStringList:
223 res.reserve( value->StringList.nCount );
224 for (
int i = 0; i < value->StringList.nCount; ++i )
225 res << QString::fromUtf8( value->StringList.paList[ i ] );
234 if ( datetime.timeSpec() == Qt::LocalTime )
236 return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
241 auto res = std::make_unique< OGRField >();
243 switch ( value.userType() )
245 case QMetaType::Type::UnknownType:
246 OGR_RawField_SetUnset( res.get() );
248 case QMetaType::Type::Bool:
250 const int val = value.toBool() ? 1 : 0;
251 if ( type == OFTInteger )
253 else if ( type == OFTInteger64 )
254 res->Integer64 = val;
255 else if ( type == OFTReal )
264 case QMetaType::Type::Int:
266 const int val = value.toInt();
267 if ( type == OFTInteger )
269 else if ( type == OFTInteger64 )
270 res->Integer64 = val;
271 else if ( type == OFTReal )
280 case QMetaType::Type::LongLong:
282 const qint64 val = value.toLongLong();
283 if ( type == OFTInteger )
285 if ( val <= std::numeric_limits<int>::max() &&
286 val >= std::numeric_limits<int>::min() )
288 res->Integer =
static_cast<int>( val );
296 else if ( type == OFTInteger64 )
297 res->Integer64 = val;
298 else if ( type == OFTReal )
300 res->Real =
static_cast<double>( val );
304 QgsDebugError(
"Unsupported output data type for LongLong" );
309 case QMetaType::Type::Double:
311 double val = value.toDouble();
312 if ( type == OFTInteger )
314 if ( val <= std::numeric_limits<int>::max() &&
315 val >= std::numeric_limits<int>::min() )
317 res->Integer =
static_cast<int>( val );
325 else if ( type == OFTInteger64 )
327 if ( val <=
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
328 val >=
static_cast<double>( std::numeric_limits<qint64>::min() ) )
330 res->Integer64 =
static_cast<qint64
>( val );
338 else if ( type == OFTReal )
344 QgsDebugError(
"Unsupported output data type for LongLong" );
349 case QMetaType::Type::QChar:
350 case QMetaType::Type::QString:
352 if ( type == OFTString )
353 res->String = CPLStrdup( value.toString().toUtf8().constData() );
361 case QMetaType::Type::QDate:
363 if ( type == OFTDate )
365 const QDate date = value.toDate();
366 res->Date.Day = date.day();
367 res->Date.Month = date.month();
368 res->Date.Year =
static_cast<GInt16
>( date.year() );
369 res->Date.TZFlag = 0;
378 case QMetaType::Type::QTime:
380 if ( type == OFTTime )
382 const QTime time = value.toTime();
383 res->Date.Hour = time.hour();
384 res->Date.Minute = time.minute();
385 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
386 res->Date.TZFlag = 0;
395 case QMetaType::Type::QDateTime:
397 if ( type == OFTDateTime )
399 const QDateTime dt = value.toDateTime();
400 const QDate date = dt.date();
401 res->Date.Day = date.day();
402 res->Date.Month = date.month();
403 res->Date.Year =
static_cast<GInt16
>( date.year() );
404 const QTime time = dt.time();
405 res->Date.Hour = time.hour();
406 res->Date.Minute = time.minute();
407 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
412 QgsDebugError(
"Unsupported output data type for DateTime" );
419 QgsDebugError(
"Unhandled variant type in variantToOGRField" );
420 OGR_RawField_SetUnset( res.get() );
436 feature.
setId( OGR_F_GetFID( ogrFet ) );
459 int fieldCount = OGR_F_GetFieldCount( ogrFet );
460 for (
int i = 0; i < fieldCount; ++i )
462 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
469 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
470 QMetaType::Type varType;
471 switch ( OGR_Fld_GetType( fldDef ) )
474 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
475 varType = QMetaType::Type::Bool;
477 varType = QMetaType::Type::Int;
480 varType = QMetaType::Type::LongLong;
483 varType = QMetaType::Type::Double;
486 varType = QMetaType::Type::QDate;
489 varType = QMetaType::Type::QTime;
492 varType = QMetaType::Type::QDateTime;
495 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
496 varType = QMetaType::Type::QVariantMap;
498 varType = QMetaType::Type::QString;
501 varType = QMetaType::Type::QString;
511 if ( attIndex < 0 || attIndex >= fields.
count() )
524 if ( !ogrFet || attIndex < 0 )
531 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
538 QgsDebugError( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
548 auto getJsonValue = [&]() ->
bool
550 const char *json = OGR_F_GetFieldAsString( ogrFet, attIndex );
553 jsonContent = encoding->toUnicode( json ).toUtf8();
555 jsonContent = QString::fromUtf8( json ).toUtf8();
559 const nlohmann::json json_element = json::parse( jsonContent.toStdString() );
563 catch (
const json::parse_error &e )
565 QgsDebugMsgLevel( QStringLiteral(
"Error parsing JSON: %1" ).arg( e.what() ), 2 );
570 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
572 switch ( field.
type() )
574 case QMetaType::Type::QString:
576 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
579 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
581 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
586 if ( value.isNull() )
587 value = QVariant( QStringLiteral(
"" ) );
592 case QMetaType::Type::Int:
593 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
595 case QMetaType::Type::Bool:
596 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
598 case QMetaType::Type::LongLong:
599 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
601 case QMetaType::Type::Double:
602 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
604 case QMetaType::Type::QDate:
605 case QMetaType::Type::QDateTime:
606 case QMetaType::Type::QTime:
608 int year, month, day, hour, minute, tzf;
610 float secondsPart = 0;
612 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
613 float millisecondPart = std::modf( second, &secondsPart );
615 if ( field.
type() == QMetaType::Type::QDate )
616 value = QDate( year, month, day );
617 else if ( field.
type() == QMetaType::Type::QTime )
618 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
621 QDateTime dt = QDateTime( QDate( year, month, day ),
622 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
623 setQTTimeZoneFromOGRTZFlag( dt, tzf );
629 case QMetaType::Type::QByteArray:
632 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
636 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
643 case QMetaType::Type::QStringList:
645 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
648 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
649 const int count = CSLCount( lst );
652 list.reserve( count );
653 for (
int i = 0; i < count; i++ )
656 list << encoding->toUnicode( lst[i] );
658 list << QString::fromUtf8( lst[i] );
666 case QMetaType::Type::QVariantList:
670 case QMetaType::Type::QString:
672 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
675 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
676 const int count = CSLCount( lst );
679 list.reserve( count );
680 for (
int i = 0; i < count; i++ )
683 list << encoding->toUnicode( lst[i] );
685 list << QString::fromUtf8( lst[i] );
693 case QMetaType::Type::Int:
695 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
699 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
702 list.reserve( count );
703 for (
int i = 0; i < count; i++ )
713 case QMetaType::Type::Double:
715 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
719 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
722 list.reserve( count );
723 for (
int i = 0; i < count; i++ )
733 case QMetaType::Type::LongLong:
735 if ( field.
typeName() != QLatin1String(
"JSON" ) || ! getJsonValue() )
739 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
742 list.reserve( count );
743 for (
int i = 0; i < count; i++ )
755 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
764 case QMetaType::Type::QVariantMap:
769 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
771 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
775 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
798 for (
int idx = 0; idx < fields.
count(); ++idx )
814 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
828 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
829 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
834 auto mp = std::make_unique< QgsMultiPoint >();
836 const int count = OGR_G_GetGeometryCount( geom );
837 mp->reserve( count );
838 for (
int i = 0; i < count; ++i )
850 int count = OGR_G_GetPointCount( geom );
851 QVector< double > x( count );
852 QVector< double > y( count );
854 double *pz =
nullptr;
860 double *pm =
nullptr;
867 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
874 auto mp = std::make_unique< QgsMultiLineString >();
876 const int count = OGR_G_GetGeometryCount( geom );
877 mp->reserve( count );
878 for (
int i = 0; i < count; ++i )
888 auto polygon = std::make_unique< QgsPolygon >();
890 const int count = OGR_G_GetGeometryCount( geom );
896 for (
int i = 1; i < count; ++i )
906 auto polygon = std::make_unique< QgsMultiPolygon >();
908 const int count = OGR_G_GetGeometryCount( geom );
909 polygon->reserve( count );
910 for (
int i = 0; i < count; ++i )
920 switch ( ogrGeomType )
1009 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
1052 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
1055 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
1056 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
1058 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
1060 OGR_G_DestroyGeometry( newGeom );
1066 int memorySize = OGR_G_WkbSize( geom );
1067 unsigned char *wkb =
new unsigned char[memorySize];
1078 if (
string.isEmpty() )
1081 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1084 QByteArray ba =
string.toUtf8();
1085 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1086 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1091 VSIUnlink( randomFileName.toUtf8().constData() );
1095 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1099 VSIUnlink( randomFileName.toUtf8().constData() );
1104 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1112 VSIUnlink( randomFileName.toUtf8().constData() );
1120 if (
string.isEmpty() )
1123 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1126 QByteArray ba =
string.toUtf8();
1127 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1128 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1133 VSIUnlink( randomFileName.toUtf8().constData() );
1137 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1141 VSIUnlink( randomFileName.toUtf8().constData() );
1147 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1153 VSIUnlink( randomFileName.toUtf8().constData() );
1162 QStringList strings;
1164 for (
qgssize i = 0; stringList[i]; ++i )
1166 strings.append( QString::fromUtf8( stringList[i] ) );
1177 char *pszWkt =
nullptr;
1178 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=NO" ).toLocal8Bit();
1179 const QByteArray formatOption = QStringLiteral(
"FORMAT=WKT2" ).toLocal8Bit();
1180 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1181 OSRExportToWktEx( srs, &pszWkt, options );
1183 const QString res( pszWkt );
1191 if ( wkt.isEmpty() )
1194 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1195 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1197 if ( authorityName && authorityCode )
1199 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1200 OGRSpatialReferenceH ogrSrsTmp = OSRNewSpatialReference(
nullptr );
1202 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1203 OSRIsSame( srs, ogrSrsTmp ) )
1208 OSRDestroySpatialReference( ogrSrsTmp );
1213#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1214 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1215 if ( coordinateEpoch > 0 )
1225 OGRSpatialReferenceH ogrSrs =
nullptr;
1231 const QString authId = crs.
authid();
1233 if ( !authId.isEmpty() )
1235 ogrSrs = OSRNewSpatialReference(
nullptr );
1236 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1239 OGRSpatialReferenceH ogrSrsFromWkt = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1240 if ( ogrSrsFromWkt )
1242 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1244 OSRDestroySpatialReference( ogrSrs );
1245 ogrSrs = ogrSrsFromWkt;
1249 OSRDestroySpatialReference( ogrSrsFromWkt );
1255 OSRDestroySpatialReference( ogrSrs );
1261 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1265 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1266#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1282 if ( !cpgEncoding.isEmpty() )
1291 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1292 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_CPG" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1298 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1299 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_LDID" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1306 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1308 | CSLT_PRESERVEQUOTES
1309 | CSLT_PRESERVEESCAPES );
1310 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1316 const thread_local QRegularExpression sToolPartRx( QStringLiteral(
"^(.*?)\\((.*)\\)$" ) );
1317 const QString stylePart( papszStyleString[i] );
1318 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1319 if ( !match.hasMatch() )
1322 const QString tool = match.captured( 1 );
1323 const QString params = match.captured( 2 );
1325 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1326 | CSLT_PRESERVEESCAPES );
1328 QVariantMap toolParts;
1329 const thread_local QRegularExpression sToolParamRx( QStringLiteral(
"^(.*?):(.*)$" ) );
1330 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1332 const QString toolPart( papszTokens[j] );
1333 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1334 if ( !match.hasMatch() )
1338 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1340 CSLDestroy( papszTokens );
1343 styles.insert( tool.toLower(), toolParts );
1345 CSLDestroy( papszStyleString );
1353 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1355 const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
1356 const QRegularExpressionMatch match = sUnitRx.match( size );
1357 if ( match.hasMatch() )
1359 value = match.captured( 1 ).toDouble();
1360 const QString unitString = match.captured( 2 );
1361 if ( unitString.compare( QLatin1String(
"px" ), Qt::CaseInsensitive ) == 0 )
1365 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1366 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1368 value *= PX_TO_PT_FACTOR;
1371 else if ( unitString.compare( QLatin1String(
"pt" ), Qt::CaseInsensitive ) == 0 )
1376 else if ( unitString.compare( QLatin1String(
"mm" ), Qt::CaseInsensitive ) == 0 )
1381 else if ( unitString.compare( QLatin1String(
"cm" ), Qt::CaseInsensitive ) == 0 )
1387 else if ( unitString.compare( QLatin1String(
"in" ), Qt::CaseInsensitive ) == 0 )
1392 else if ( unitString.compare( QLatin1String(
"g" ), Qt::CaseInsensitive ) == 0 )
1397 QgsDebugError( QStringLiteral(
"Unknown unit %1" ).arg( unitString ) );
1401 QgsDebugError( QStringLiteral(
"Could not parse style size %1" ).arg( size ) );
1406 auto convertColor = [](
const QString & string ) -> QColor
1408 if (
string.isEmpty() )
1411 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral(
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
1412 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1413 if ( match.hasMatch() )
1416 return QColor( QStringLiteral(
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
1420 return QColor(
string );
1424 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1426 QColor color = convertColor( lineStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1430 convertSize( lineStyle.value( QStringLiteral(
"w" ) ).toString(), lineWidth, lineWidthUnit );
1433 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-pen-(\\d+)" ) );
1434 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1435 if ( match.hasMatch() )
1437 const int penId = match.captured( 1 ).toInt();
1444 auto simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1445 simpleLine->setWidthUnit( lineWidthUnit );
1448 const QString pattern = lineStyle.value( QStringLiteral(
"p" ) ).toString();
1449 if ( !pattern.isEmpty() )
1451 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
1452 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1453 if ( match.hasMatch() )
1455 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1456 QVector< qreal > dashPattern;
1458 for (
const QString &val : patternValues )
1461 convertSize( val + match.captured( 2 ), length, patternUnits );
1462 dashPattern.push_back( length * lineWidth * 2 );
1465 simpleLine->setCustomDashVector( dashPattern );
1466 simpleLine->setCustomDashPatternUnit( patternUnits );
1467 simpleLine->setUseCustomDashPattern(
true );
1471 Qt::PenCapStyle capStyle = Qt::FlatCap;
1472 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1474 const QString
id = lineStyle.value( QStringLiteral(
"id" ) ).toString();
1475 if (
id.contains( QLatin1String(
"mapinfo-pen" ), Qt::CaseInsensitive ) )
1480 capStyle = Qt::RoundCap;
1481 joinStyle = Qt::RoundJoin;
1485 const QString penCap = lineStyle.value( QStringLiteral(
"cap" ) ).toString();
1486 if ( penCap.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1488 capStyle = Qt::FlatCap;
1490 else if ( penCap.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1492 capStyle = Qt::RoundCap;
1494 else if ( penCap.compare( QLatin1String(
"p" ), Qt::CaseInsensitive ) == 0 )
1496 capStyle = Qt::SquareCap;
1498 simpleLine->setPenCapStyle( capStyle );
1501 const QString penJoin = lineStyle.value( QStringLiteral(
"j" ) ).toString();
1502 if ( penJoin.compare( QLatin1String(
"m" ), Qt::CaseInsensitive ) == 0 )
1504 joinStyle = Qt::MiterJoin;
1506 else if ( penJoin.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1508 joinStyle = Qt::RoundJoin;
1510 else if ( penJoin.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1512 joinStyle = Qt::BevelJoin;
1514 simpleLine->setPenJoinStyle( joinStyle );
1516 const QString priority = lineStyle.value( QStringLiteral(
"l" ) ).toString();
1517 if ( !priority.isEmpty() )
1519 simpleLine->setRenderingPass( priority.toInt() );
1521 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1524 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1526 const QColor foreColor = convertColor( brushStyle.value( QStringLiteral(
"fc" ), QStringLiteral(
"#000000" ) ).toString() );
1527 const QColor backColor = convertColor( brushStyle.value( QStringLiteral(
"bc" ), QString() ).toString() );
1529 const QString
id = brushStyle.value( QStringLiteral(
"id" ) ).toString();
1532 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-brush-(\\d+)" ) );
1533 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1534 if ( match.hasMatch() )
1536 const int brushId = match.captured( 1 ).toInt();
1543 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-brush-(\\d+)" ) );
1544 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1546 Qt::BrushStyle style = Qt::SolidPattern;
1547 if ( ogrMatch.hasMatch() )
1549 const int brushId = ogrMatch.captured( 1 ).toInt();
1553 style = Qt::SolidPattern;
1557 style = Qt::NoBrush;
1561 style = Qt::HorPattern;
1565 style = Qt::VerPattern;
1569 style = Qt::FDiagPattern;
1573 style = Qt::BDiagPattern;
1577 style = Qt::CrossPattern;
1581 style = Qt::DiagCrossPattern;
1587 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1589 auto backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1590 backgroundFill->setLocked(
true );
1591 backgroundFill->setStrokeStyle( Qt::NoPen );
1592 layers << backgroundFill.release();
1595 auto foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1596 foregroundFill->setBrushStyle( style );
1597 foregroundFill->setStrokeStyle( Qt::NoPen );
1599 const QString priority = brushStyle.value( QStringLiteral(
"l" ) ).toString();
1600 if ( !priority.isEmpty() )
1602 foregroundFill->setRenderingPass( priority.toInt() );
1604 layers << foregroundFill.release();
1605 return std::make_unique< QgsFillSymbol >( layers );
1608 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1610 const QColor color = convertColor( symbolStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1614 convertSize( symbolStyle.value( QStringLiteral(
"s" ) ).toString(), symbolSize, symbolSizeUnit );
1616 const double angle = symbolStyle.value( QStringLiteral(
"a" ), QStringLiteral(
"0" ) ).toDouble();
1618 const QString
id = symbolStyle.value( QStringLiteral(
"id" ) ).toString();
1621 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-sym-(\\d+)" ) );
1622 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1623 if ( match.hasMatch() )
1625 const int symbolId = match.captured( 1 ).toInt();
1636 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1638 const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral(
"font-sym-(\\d+)" ) );
1639 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1640 if ( fontMatch.hasMatch() )
1642 const int symId = fontMatch.captured( 1 ).toInt();
1643 const QStringList families = symbolStyle.value( QStringLiteral(
"f" ), QString() ).toString().split(
',' );
1645 bool familyFound =
false;
1648 for (
const QString &family : std::as_const( families ) )
1656 fontFamily = processedFamily;
1663 auto fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1664 fontMarker->setSizeUnit( symbolSizeUnit );
1665 fontMarker->setAngle( -angle );
1667 fontMarker->setColor( color );
1669 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1670 if ( strokeColor.isValid() )
1672 fontMarker->setStrokeColor( strokeColor );
1673 fontMarker->setStrokeWidth( 1 );
1678 fontMarker->setStrokeWidth( 0 );
1681 markerLayer = std::move( fontMarker );
1683 else if ( !families.empty() )
1692 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-sym-(\\d+)" ) );
1693 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1696 bool isFilled =
true;
1697 if ( ogrMatch.hasMatch() )
1699 const int symId = ogrMatch.captured( 1 ).toInt();
1762 auto simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
1763 simpleMarker->setSizeUnit( symbolSizeUnit );
1764 simpleMarker->setStrokeWidth( 1.0 );
1769 simpleMarker->setColor( color );
1770 simpleMarker->setStrokeStyle( Qt::NoPen );
1774 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1775 simpleMarker->setStrokeColor( color );
1778 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1779 if ( strokeColor.isValid() )
1781 simpleMarker->setStrokeColor( strokeColor );
1782 simpleMarker->setStrokeStyle( Qt::SolidLine );
1785 markerLayer = std::move( simpleMarker );
1788 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1794 if ( styles.contains( QStringLiteral(
"symbol" ) ) )
1796 const QVariantMap symbolStyle = styles.value( QStringLiteral(
"symbol" ) ).toMap();
1797 return convertSymbol( symbolStyle );
1805 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1808 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1809 return convertPen( lineStyle );
1818 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1819 if ( styles.contains( QStringLiteral(
"brush" ) ) )
1821 const QVariantMap brushStyle = styles.value( QStringLiteral(
"brush" ) ).toMap();
1822 fillSymbol = convertBrush( brushStyle );
1826 auto emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1827 emptyFill->setBrushStyle( Qt::NoBrush );
1828 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1831 std::unique_ptr< QgsSymbol > penSymbol;
1832 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1834 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1835 penSymbol = convertPen( lineStyle );
1840 const int count = penSymbol->symbolLayerCount();
1850 for (
int i = 0; i < count; ++i )
1852 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1853 layer->setLocked(
true );
1854 fillSymbol->appendSymbolLayer( layer.release() );
1870 variantType = QMetaType::Type::UnknownType;
1871 variantSubType = QMetaType::Type::UnknownType;
1876 if ( ogrSubType == OFSTBoolean )
1878 variantType = QMetaType::Type::Bool;
1881 variantType = QMetaType::Type::Int;
1884 variantType = QMetaType::Type::LongLong;
1887 variantType = QMetaType::Type::Double;
1890 variantType = QMetaType::Type::QDate;
1893 variantType = QMetaType::Type::QTime;
1896 variantType = QMetaType::Type::QDateTime;
1900 variantType = QMetaType::Type::QByteArray;
1905 if ( ogrSubType == OFSTJSON )
1907 variantType = QMetaType::Type::QVariantMap;
1908 variantSubType = QMetaType::Type::QString;
1912 variantType = QMetaType::Type::QString;
1917 case OFTWideStringList:
1918 variantType = QMetaType::Type::QStringList;
1919 variantSubType = QMetaType::Type::QString;
1922 case OFTIntegerList:
1923 variantType = QMetaType::Type::QVariantList;
1924 variantSubType = QMetaType::Type::Int;
1928 variantType = QMetaType::Type::QVariantList;
1929 variantSubType = QMetaType::Type::Double;
1932 case OFTInteger64List:
1933 variantType = QMetaType::Type::QVariantList;
1934 variantSubType = QMetaType::Type::LongLong;
1941 ogrSubType = OFSTNone;
1942 switch ( variantType )
1944 case QMetaType::Type::Bool:
1945 ogrType = OFTInteger;
1946 ogrSubType = OFSTBoolean;
1949 case QMetaType::Type::Int:
1950 ogrType = OFTInteger;
1953 case QMetaType::Type::LongLong:
1954 ogrType = OFTInteger64;
1957 case QMetaType::Type::Double:
1961 case QMetaType::Type::QChar:
1962 case QMetaType::Type::QString:
1963 ogrType = OFTString;
1966 case QMetaType::Type::QStringList:
1967 ogrType = OFTStringList;
1970 case QMetaType::Type::QByteArray:
1971 ogrType = OFTBinary;
1974 case QMetaType::Type::QDate:
1978 case QMetaType::Type::QTime:
1981 case QMetaType::Type::QDateTime:
1982 ogrType = OFTDateTime;
1986 ogrType = OFTString;
1993 if (
string.isEmpty() )
2001 res =
string.toInt( &ok );
2005 res =
string.toLongLong( &ok );
2009 res =
string.toDouble( &ok );
2019 res = QDate::fromString(
string, Qt::ISODate );
2024 res = QTime::fromString(
string, Qt::ISODate );
2029 res = QDateTime::fromString(
string, Qt::ISODate );
2039 return ok ? res : QVariant();
2047 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2049 int nMaxIntLen = 11;
2050 int nMaxInt64Len = 21;
2051 int nMaxDoubleLen = 20;
2052 int nMaxDoublePrec = 15;
2054 if ( driverName == QLatin1String(
"GPKG" ) )
2064 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2068 <<
QgsVectorDataProvider::NativeType( QObject::tr(
"Decimal number (real)" ), QStringLiteral(
"double" ), QMetaType::Type::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
2071 if ( driverName == QLatin1String(
"GPKG" ) )
2072 nativeTypes <<
QgsVectorDataProvider::NativeType( QObject::tr(
"JSON (string)" ), QStringLiteral(
"JSON" ), QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
2074 bool supportsDate =
true;
2075 bool supportsTime =
true;
2076 bool supportsDateTime =
true;
2077 bool supportsBinary =
false;
2078 bool supportIntegerList =
false;
2079 bool supportInteger64List =
false;
2080 bool supportRealList =
false;
2081 bool supportsStringList =
false;
2085 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2087 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2088 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2089 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2090 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2091 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2092 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2093 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2094 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2095 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2096 CSLDestroy( papszTokens );
2101#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2102 if ( driverName == QLatin1String(
"ESRI Shapefile" ) )
2104 supportsDateTime =
false;
2118 if ( supportsDateTime )
2123 if ( supportsBinary )
2128 if ( supportIntegerList )
2133 if ( supportInteger64List )
2138 if ( supportRealList )
2143 if ( supportsStringList )
2149 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2150 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2161#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2167 const QString name{ OGR_FldDomain_GetName( domain ) };
2168 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2170 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
2171 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
2172 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2173 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2176 std::unique_ptr< QgsFieldDomain > res;
2177 switch ( OGR_FldDomain_GetDomainType( domain ) )
2181 QList< QgsCodedValue > values;
2182 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2183 while ( codedValue && codedValue->pszCode )
2185 const QString code( codedValue->pszCode );
2190 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2196 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2203 bool minIsInclusive =
false;
2204 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2209 bool maxIsInclusive =
false;
2210 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2215 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2216 minValue, minIsInclusive,
2217 maxValue, maxIsInclusive );
2222 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2223 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2227 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2229 case OFDMP_DEFAULT_VALUE:
2235 case OFDMP_GEOMETRY_WEIGHTED:
2240 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2242 case OFDSP_DEFAULT_VALUE:
2245 case OFDSP_DUPLICATE:
2248 case OFDSP_GEOMETRY_RATIO:
2260 OGRFieldType domainFieldType = OFTInteger;
2261 OGRFieldSubType domainFieldSubType = OFSTNone;
2264 OGRFieldDomainH res =
nullptr;
2265 switch ( domain->
type() )
2269 std::vector< OGRCodedValue > enumeration;
2270 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2271 enumeration.reserve( values.size() );
2274 OGRCodedValue codedValue;
2275 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2276 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2277 enumeration.push_back( codedValue );
2280 last.pszCode =
nullptr;
2281 last.pszValue =
nullptr;
2282 enumeration.push_back( last );
2283 res = OGR_CodedFldDomain_Create(
2284 domain->
name().toUtf8().constData(),
2291 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2293 CPLFree( value.pszCode );
2294 CPLFree( value.pszValue );
2301 std::unique_ptr< OGRField > min =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2302 std::unique_ptr< OGRField > max =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2305 res = OGR_RangeFldDomain_Create(
2306 domain->
name().toUtf8().constData(),
2311 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2313 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2320 res = OGR_GlobFldDomain_Create(
2321 domain->
name().toUtf8().constData(),
2325 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2334 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2337 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2340 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2355 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2358 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2361 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2374#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2378 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2380 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2382 QVariantMap leftTableUriParts = datasetUriParts;
2383 leftTableUriParts.insert( QStringLiteral(
"layerName" ), leftTableName );
2384 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2386 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2387 QVariantMap rightTableUriParts = datasetUriParts;
2388 rightTableUriParts.insert( QStringLiteral(
"layerName" ), rightTableName );
2389 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2391 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2392 QString mappingTableSource;
2393 if ( !mappingTableName.isEmpty() )
2395 QVariantMap mappingTableUriParts = datasetUriParts;
2396 mappingTableUriParts.insert( QStringLiteral(
"layerName" ), mappingTableName );
2397 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2400 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2402 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2404 CSLDestroy( cslLeftTableFieldNames );
2406 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2408 CSLDestroy( cslRightTableFieldNames );
2410 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2412 CSLDestroy( cslLeftMappingTableFieldNames );
2414 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2416 CSLDestroy( cslRightMappingTableFieldNames );
2418 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2419 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2420 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2422 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2424 switch ( relationshipType )
2430 case GRT_ASSOCIATION:
2434 case GRT_AGGREGATION:
2435 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2439 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2441 switch ( eCardinality )
2443 case GRC_ONE_TO_ONE:
2446 case GRC_ONE_TO_MANY:
2449 case GRC_MANY_TO_ONE:
2452 case GRC_MANY_TO_MANY:
2457 switch ( cardinality )
2466 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2467 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2482 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2483 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2501 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2505 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2508 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2511 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2514 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2521 const QString leftTableName = leftParts.value( QStringLiteral(
"layerName" ) ).toString();
2522 if ( leftTableName.isEmpty() )
2524 error = QObject::tr(
"Parent table name was not set" );
2529 const QString rightTableName = rightParts.value( QStringLiteral(
"layerName" ) ).toString();
2530 if ( rightTableName.isEmpty() )
2532 error = QObject::tr(
"Child table name was not set" );
2536 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != rightParts.value( QStringLiteral(
"path" ) ).toString() )
2538 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2542 QString mappingTableName;
2546 mappingTableName = mappingParts.value( QStringLiteral(
"layerName" ) ).toString();
2547 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != mappingParts.value( QStringLiteral(
"path" ) ).toString() )
2549 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2555 leftTableName.toLocal8Bit().constData(),
2556 rightTableName.toLocal8Bit().constData(),
2561 int count = leftFieldNames.count();
2562 char **lst =
nullptr;
2565 for (
const QString &
string : leftFieldNames )
2567 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2570 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2575 count = rightFieldNames.count();
2579 for (
const QString &
string : rightFieldNames )
2581 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2584 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2587 if ( !mappingTableName.isEmpty() )
2589 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2593 int count = leftFieldNames.count();
2597 for (
const QString &
string : leftFieldNames )
2599 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2602 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2607 count = rightFieldNames.count();
2611 for (
const QString &
string : rightFieldNames )
2613 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2616 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2624 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2628 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2634 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2636 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2640 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2648 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2652 errCause = QObject::tr(
"No styles available on DB" );
2656 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2659 errCause = QObject::tr(
"No styles available on DB" );
2663 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2665 OGR_L_ResetReading( hLayer );
2667 QList<qlonglong> listTimestamp;
2668 QMap<int, QString> mapIdToStyleName;
2669 QMap<int, QString> mapIdToDescription;
2670 QMap<qlonglong, QList<int> > mapTimestampToId;
2671 int numberOfRelatedStyles = 0;
2679 QString tableName( QString::fromUtf8(
2680 OGR_F_GetFieldAsString( hFeature.get(),
2681 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2682 QString geometryColumn( QString::fromUtf8(
2683 OGR_F_GetFieldAsString( hFeature.get(),
2684 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2685 QString styleName( QString::fromUtf8(
2686 OGR_F_GetFieldAsString( hFeature.get(),
2687 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2688 QString description( QString::fromUtf8(
2689 OGR_F_GetFieldAsString( hFeature.get(),
2690 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2691 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2692 if ( tableName == layerName &&
2693 geometryColumn == geomColumn )
2696 QString id( QString::number( fid ) );
2698 names.append( styleName );
2699 descriptions.append( description );
2700 ++ numberOfRelatedStyles;
2704 int year, month, day, hour, minute, second, TZ;
2705 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2706 &year, &month, &day, &hour, &minute, &second, &TZ );
2707 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2708 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2710 listTimestamp.append( ts );
2711 mapIdToStyleName[fid] = styleName;
2712 mapIdToDescription[fid] = description;
2713 mapTimestampToId[ts].append( fid );
2717 std::sort( listTimestamp.begin(), listTimestamp.end() );
2719 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2721 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2722 for (
int j = 0; j < listId.size(); j++ )
2724 int fid = listId[j];
2725 QString id( QString::number( fid ) );
2727 names.append( mapIdToStyleName[fid] );
2728 descriptions.append( mapIdToDescription[fid] );
2732 return numberOfRelatedStyles;
2740 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2744 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2746 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2747 " AND f_table_name=%1"
2748 " AND f_geometry_column=%2"
2749 " AND styleName=%3" )
2750 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2751 QgsOgrProviderUtils::quotedValue( geomColumn ),
2752 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2753 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2754 OGR_L_ResetReading( hLayer );
2756 OGR_L_ResetReading( hLayer );
2766 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2770 errCause = QObject::tr(
"No styles available on DB" );
2775 int id = styleId.toInt( &ok );
2778 errCause = QObject::tr(
"Invalid style identifier" );
2785 errCause = QObject::tr(
"No style corresponding to style identifier" );
2789 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2790 QString styleQML( QString::fromUtf8(
2791 OGR_F_GetFieldAsString( hFeature.get(),
2792 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2793 OGR_L_ResetReading( hLayer );
2802 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2807 errCause = QObject::tr(
"Connection to database failed" );
2812 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2814 errCause = QObject::tr(
"Error executing the delete query." );
2827 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2831 errCause = QObject::tr(
"No styles available on DB" );
2835 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2836 " AND f_table_name=%1"
2837 " AND f_geometry_column=%2"
2838 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2839 ",update_time DESC" )
2840 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2841 QgsOgrProviderUtils::quotedValue( geomColumn ) );
2842 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2843 OGR_L_ResetReading( hLayer );
2844 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2846 qlonglong moreRecentTimestamp = 0;
2852 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2854 styleQML = QString::fromUtf8(
2855 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2856 styleName = QString::fromUtf8(
2857 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2861 int year, month, day, hour, minute, second, TZ;
2862 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2863 &year, &month, &day, &hour, &minute, &second, &TZ );
2864 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2865 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2866 if ( ts > moreRecentTimestamp )
2868 moreRecentTimestamp = ts;
2869 styleQML = QString::fromUtf8(
2870 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2871 styleName = QString::fromUtf8(
2872 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2875 OGR_L_ResetReading( hLayer );
2881 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
2882 const QString &styleName,
const QString &styleDescription,
2883 const QString &uiFileContent,
bool useAsDefault, QString &errCause
2887 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2894 char **options =
nullptr;
2896 options = CSLSetNameValue( options,
"FID",
"id" );
2897 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
2898 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
2899 CSLDestroy( options );
2902 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2908 OGR_Fld_SetWidth( fld.get(), 256 );
2909 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2913 OGR_Fld_SetWidth( fld.get(), 256 );
2914 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2918 OGR_Fld_SetWidth( fld.get(), 256 );
2919 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2923 OGR_Fld_SetWidth( fld.get(), 256 );
2924 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2928 OGR_Fld_SetWidth( fld.get(), 30 );
2929 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2933 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2937 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2941 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
2942 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2946 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2950 OGR_Fld_SetWidth( fld.get(), 30 );
2951 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2955 OGR_Fld_SetWidth( fld.get(), 30 );
2956 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2960 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
2961 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2965 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2970 QString realStyleName =
2971 styleName.isEmpty() ? layerName : styleName;
2973 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2977 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
2978 " AND f_table_name=%1"
2979 " AND f_geometry_column=%2" )
2980 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
2981 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
2982 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
2986 OGR_F_SetFieldInteger( hFeature.get(),
2987 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
2989 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
2992 QgsDebugError( QStringLiteral(
"Could not unset previous useAsDefault style" ) );
2997 QString checkQuery = QStringLiteral(
"f_table_schema=''"
2998 " AND f_table_name=%1"
2999 " AND f_geometry_column=%2"
3000 " AND styleName=%3" )
3001 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3002 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
3003 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
3004 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
3005 OGR_L_ResetReading( hLayer );
3007 OGR_L_ResetReading( hLayer );
3016 hFeature.reset( OGR_F_Create( hLayerDefn ) );
3017 OGR_F_SetFieldString( hFeature.get(),
3018 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
3020 OGR_F_SetFieldString( hFeature.get(),
3021 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
3023 OGR_F_SetFieldString( hFeature.get(),
3024 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
3025 layerName.toUtf8().constData() );
3026 OGR_F_SetFieldString( hFeature.get(),
3027 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
3028 geomColumn.toUtf8().constData() );
3029 OGR_F_SetFieldString( hFeature.get(),
3030 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
3031 realStyleName.toUtf8().constData() );
3032 if ( !uiFileContent.isEmpty() )
3034 OGR_F_SetFieldString( hFeature.get(),
3035 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
3036 uiFileContent.toUtf8().constData() );
3039 OGR_F_SetFieldString( hFeature.get(),
3040 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3041 qmlStyle.toUtf8().constData() );
3042 OGR_F_SetFieldString( hFeature.get(),
3043 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3044 sldStyle.toUtf8().constData() );
3045 OGR_F_SetFieldInteger( hFeature.get(),
3046 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3047 useAsDefault ? 1 : 0 );
3048 OGR_F_SetFieldString( hFeature.get(),
3049 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3050 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3051 OGR_F_SetFieldString( hFeature.get(),
3052 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3057 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3059 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3064 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 Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE 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< GDALRelationshipH >::type, GDALRelationshipDeleter > relationship_unique_ptr
Scoped GDAL relationship.
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< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
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
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.