38#include "qgsogrproviderutils.h"
47using namespace Qt::StringLiterals;
49#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
60#include <QJsonDocument>
65#include <QRegularExpression>
67#include "ogr_srs_api.h"
69#include "nlohmann/json.hpp"
73 OGR_DS_Destroy( source );
79 OGR_G_DestroyGeometry( geometry );
84 OGR_Fld_Destroy( definition );
89 OGR_F_Destroy( feature );
106 CPLPushErrorHandler( CPLQuietErrorHandler );
107 GDALDeleteDataset( driver, path.toUtf8().constData() );
108 CPLPopErrorHandler();
119 GDALDestroyWarpOptions( options );
122#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
125 GDALDestroyRelationship( relationship );
129static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt,
int nTZFlag )
136 else if ( nTZFlag == 1 )
138 dt.setTimeSpec( Qt::LocalTime );
140 else if ( nTZFlag == 100 )
142 dt.setTimeSpec( Qt::UTC );
148 dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
154 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
160 return value->Integer;
163 return value->Integer64;
170 return QString::fromUtf8( value->String );
173 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
177 float secondsPart = 0;
178 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
179 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
184 float secondsPart = 0;
185 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
186 QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
187 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
188 setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
194 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
200 res.reserve( value->IntegerList.nCount );
201 for (
int i = 0; i < value->IntegerList.nCount; ++i )
202 res << value->IntegerList.paList[ i ];
206 case OFTInteger64List:
209 res.reserve( value->Integer64List.nCount );
210 for (
int i = 0; i < value->Integer64List.nCount; ++i )
211 res << value->Integer64List.paList[ i ];
218 res.reserve( value->RealList.nCount );
219 for (
int i = 0; i < value->RealList.nCount; ++i )
220 res << value->RealList.paList[ i ];
225 case OFTWideStringList:
228 res.reserve( value->StringList.nCount );
229 for (
int i = 0; i < value->StringList.nCount; ++i )
230 res << QString::fromUtf8( value->StringList.paList[ i ] );
239 if ( datetime.timeSpec() == Qt::LocalTime )
241 return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
246 auto res = std::make_unique< OGRField >();
248 switch ( value.userType() )
250 case QMetaType::Type::UnknownType:
251 OGR_RawField_SetUnset( res.get() );
253 case QMetaType::Type::Bool:
255 const int val = value.toBool() ? 1 : 0;
256 if ( type == OFTInteger )
258 else if ( type == OFTInteger64 )
259 res->Integer64 = val;
260 else if ( type == OFTReal )
269 case QMetaType::Type::Int:
271 const int val = value.toInt();
272 if ( type == OFTInteger )
274 else if ( type == OFTInteger64 )
275 res->Integer64 = val;
276 else if ( type == OFTReal )
285 case QMetaType::Type::LongLong:
287 const qint64 val = value.toLongLong();
288 if ( type == OFTInteger )
290 if ( val <= std::numeric_limits<int>::max() &&
291 val >= std::numeric_limits<int>::min() )
293 res->Integer =
static_cast<int>( val );
301 else if ( type == OFTInteger64 )
302 res->Integer64 = val;
303 else if ( type == OFTReal )
305 res->Real =
static_cast<double>( val );
309 QgsDebugError(
"Unsupported output data type for LongLong" );
314 case QMetaType::Type::Double:
316 double val = value.toDouble();
317 if ( type == OFTInteger )
319 if ( val <= std::numeric_limits<int>::max() &&
320 val >= std::numeric_limits<int>::min() )
322 res->Integer =
static_cast<int>( val );
330 else if ( type == OFTInteger64 )
332 if ( val <=
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
333 val >=
static_cast<double>( std::numeric_limits<qint64>::min() ) )
335 res->Integer64 =
static_cast<qint64
>( val );
343 else if ( type == OFTReal )
349 QgsDebugError(
"Unsupported output data type for LongLong" );
354 case QMetaType::Type::QChar:
355 case QMetaType::Type::QString:
357 if ( type == OFTString )
358 res->String = CPLStrdup( value.toString().toUtf8().constData() );
366 case QMetaType::Type::QDate:
368 if ( type == OFTDate )
370 const QDate date = value.toDate();
371 res->Date.Day = date.day();
372 res->Date.Month = date.month();
373 res->Date.Year =
static_cast<GInt16
>( date.year() );
374 res->Date.TZFlag = 0;
383 case QMetaType::Type::QTime:
385 if ( type == OFTTime )
387 const QTime time = value.toTime();
388 res->Date.Hour = time.hour();
389 res->Date.Minute = time.minute();
390 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
391 res->Date.TZFlag = 0;
400 case QMetaType::Type::QDateTime:
402 if ( type == OFTDateTime )
404 const QDateTime dt = value.toDateTime();
405 const QDate date = dt.date();
406 res->Date.Day = date.day();
407 res->Date.Month = date.month();
408 res->Date.Year =
static_cast<GInt16
>( date.year() );
409 const QTime time = dt.time();
410 res->Date.Hour = time.hour();
411 res->Date.Minute = time.minute();
412 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
417 QgsDebugError(
"Unsupported output data type for DateTime" );
424 QgsDebugError(
"Unhandled variant type in variantToOGRField" );
425 OGR_RawField_SetUnset( res.get() );
441 feature.
setId( OGR_F_GetFID( ogrFet ) );
464 int fieldCount = OGR_F_GetFieldCount( ogrFet );
465 for (
int i = 0; i < fieldCount; ++i )
467 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
474 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
475 QMetaType::Type varType;
476 switch ( OGR_Fld_GetType( fldDef ) )
479 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
480 varType = QMetaType::Type::Bool;
482 varType = QMetaType::Type::Int;
485 varType = QMetaType::Type::LongLong;
488 varType = QMetaType::Type::Double;
491 varType = QMetaType::Type::QDate;
494 varType = QMetaType::Type::QTime;
497 varType = QMetaType::Type::QDateTime;
500 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
501 varType = QMetaType::Type::QVariantMap;
503 varType = QMetaType::Type::QString;
506 varType = QMetaType::Type::QString;
516 if ( attIndex < 0 || attIndex >= fields.
count() )
529 if ( !ogrFet || attIndex < 0 )
536 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
543 QgsDebugError( u
"ogrFet->GetFieldDefnRef(attindex) returns NULL"_s );
553 auto getJsonValue = [&]() ->
bool
555 const char *json = OGR_F_GetFieldAsString( ogrFet, attIndex );
558 jsonContent = encoding->toUnicode( json ).toUtf8();
560 jsonContent = QString::fromUtf8( json ).toUtf8();
564 const nlohmann::json json_element = json::parse( jsonContent.toStdString() );
568 catch (
const json::parse_error &e )
575 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
577 switch ( field.
type() )
579 case QMetaType::Type::QString:
581 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
584 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
586 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
591 if ( value.isNull() )
592 value = QVariant( u
""_s );
597 case QMetaType::Type::Int:
598 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
600 case QMetaType::Type::Bool:
601 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
603 case QMetaType::Type::LongLong:
604 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
606 case QMetaType::Type::Double:
607 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
609 case QMetaType::Type::QDate:
610 case QMetaType::Type::QDateTime:
611 case QMetaType::Type::QTime:
613 int year, month, day, hour, minute, tzf;
615 float secondsPart = 0;
617 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
618 float millisecondPart = std::modf( second, &secondsPart );
620 if ( field.
type() == QMetaType::Type::QDate )
621 value = QDate( year, month, day );
622 else if ( field.
type() == QMetaType::Type::QTime )
623 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
626 QDateTime dt = QDateTime( QDate( year, month, day ),
627 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
628 setQTTimeZoneFromOGRTZFlag( dt, tzf );
634 case QMetaType::Type::QByteArray:
637 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
641 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
648 case QMetaType::Type::QStringList:
650 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
653 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
654 const int count = CSLCount( lst );
657 list.reserve( count );
658 for (
int i = 0; i < count; i++ )
661 list << encoding->toUnicode( lst[i] );
663 list << QString::fromUtf8( lst[i] );
671 case QMetaType::Type::QVariantList:
675 case QMetaType::Type::QString:
677 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
680 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
681 const int count = CSLCount( lst );
684 list.reserve( count );
685 for (
int i = 0; i < count; i++ )
688 list << encoding->toUnicode( lst[i] );
690 list << QString::fromUtf8( lst[i] );
698 case QMetaType::Type::Int:
700 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
704 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
707 list.reserve( count );
708 for (
int i = 0; i < count; i++ )
718 case QMetaType::Type::Double:
720 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
724 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
727 list.reserve( count );
728 for (
int i = 0; i < count; i++ )
738 case QMetaType::Type::LongLong:
740 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
744 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
747 list.reserve( count );
748 for (
int i = 0; i < count; i++ )
760 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
769 case QMetaType::Type::QVariantMap:
774 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
776 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
780 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
803 for (
int idx = 0; idx < fields.
count(); ++idx )
819 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
833 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
834 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
839 auto mp = std::make_unique< QgsMultiPoint >();
841 const int count = OGR_G_GetGeometryCount( geom );
842 mp->reserve( count );
843 for (
int i = 0; i < count; ++i )
855 int count = OGR_G_GetPointCount( geom );
856 QVector< double > x( count );
857 QVector< double > y( count );
859 double *pz =
nullptr;
865 double *pm =
nullptr;
872 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
879 auto mp = std::make_unique< QgsMultiLineString >();
881 const int count = OGR_G_GetGeometryCount( geom );
882 mp->reserve( count );
883 for (
int i = 0; i < count; ++i )
893 auto polygon = std::make_unique< QgsPolygon >();
895 const int count = OGR_G_GetGeometryCount( geom );
901 for (
int i = 1; i < count; ++i )
911 auto polygon = std::make_unique< QgsMultiPolygon >();
913 const int count = OGR_G_GetGeometryCount( geom );
914 polygon->reserve( count );
915 for (
int i = 0; i < count; ++i )
925 auto polyhedralSurface = std::make_unique< QgsPolyhedralSurface >();
927 const int count = OGR_G_GetGeometryCount( geom );
928 for (
int i = 0; i < count; ++i )
933 return polyhedralSurface;
938 switch ( ogrGeomType )
1082 return approx ? wkbLineString : wkbUnknown;
1084 return approx ? wkbLineString25D : wkbUnknown;
1086 return approx ? wkbLineStringM : wkbUnknown;
1088 return approx ? wkbLineStringZM : wkbUnknown;
1128 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
1176 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
1179 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
1180 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
1182 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
1184 OGR_G_DestroyGeometry( newGeom );
1190 int memorySize = OGR_G_WkbSize( geom );
1191 unsigned char *wkb =
new unsigned char[memorySize];
1202 if (
string.isEmpty() )
1205 QString randomFileName = u
"/vsimem/%1"_s.arg( QUuid::createUuid().toString() );
1208 QByteArray ba =
string.toUtf8();
1209 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1210 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1215 VSIUnlink( randomFileName.toUtf8().constData() );
1219 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1223 VSIUnlink( randomFileName.toUtf8().constData() );
1228 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1236 VSIUnlink( randomFileName.toUtf8().constData() );
1244 if (
string.isEmpty() )
1247 QString randomFileName = u
"/vsimem/%1"_s.arg( QUuid::createUuid().toString() );
1250 QByteArray ba =
string.toUtf8();
1251 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1252 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1257 VSIUnlink( randomFileName.toUtf8().constData() );
1261 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1265 VSIUnlink( randomFileName.toUtf8().constData() );
1271 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1277 VSIUnlink( randomFileName.toUtf8().constData() );
1286 QStringList strings;
1288 for (
qgssize i = 0; stringList[i]; ++i )
1290 strings.append( QString::fromUtf8( stringList[i] ) );
1301 char *pszWkt =
nullptr;
1302 const QByteArray multiLineOption = u
"MULTILINE=NO"_s.toLocal8Bit();
1303 const QByteArray formatOption = u
"FORMAT=WKT2"_s.toLocal8Bit();
1304 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1305 OSRExportToWktEx( srs, &pszWkt, options );
1307 const QString res( pszWkt );
1315 if ( wkt.isEmpty() )
1318 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1319 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1321 if ( authorityName && authorityCode )
1323 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1324 OGRSpatialReferenceH ogrSrsTmp = OSRNewSpatialReference(
nullptr );
1326 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1327 OSRIsSame( srs, ogrSrsTmp ) )
1332 OSRDestroySpatialReference( ogrSrsTmp );
1337#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1338 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1339 if ( coordinateEpoch > 0 )
1349 OGRSpatialReferenceH ogrSrs =
nullptr;
1355 const QString authId = crs.
authid();
1357 if ( !authId.isEmpty() )
1359 ogrSrs = OSRNewSpatialReference(
nullptr );
1360 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1363 OGRSpatialReferenceH ogrSrsFromWkt = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1364 if ( ogrSrsFromWkt )
1366 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1368 OSRDestroySpatialReference( ogrSrs );
1369 ogrSrs = ogrSrsFromWkt;
1373 OSRDestroySpatialReference( ogrSrsFromWkt );
1379 OSRDestroySpatialReference( ogrSrs );
1385 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1389 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1390#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1406 if ( !cpgEncoding.isEmpty() )
1415 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1416 return layer ? layer->GetMetadataItem( u
"ENCODING_FROM_CPG"_s, u
"SHAPEFILE"_s ) : QString();
1422 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1423 return layer ? layer->GetMetadataItem( u
"ENCODING_FROM_LDID"_s, u
"SHAPEFILE"_s ) : QString();
1430 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1432 | CSLT_PRESERVEQUOTES
1433 | CSLT_PRESERVEESCAPES );
1434 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1440 const thread_local QRegularExpression sToolPartRx( u
"^(.*?)\\((.*)\\)$"_s );
1441 const QString stylePart( papszStyleString[i] );
1442 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1443 if ( !match.hasMatch() )
1446 const QString tool = match.captured( 1 );
1447 const QString params = match.captured( 2 );
1449 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1450 | CSLT_PRESERVEESCAPES );
1452 QVariantMap toolParts;
1453 const thread_local QRegularExpression sToolParamRx( u
"^(.*?):(.*)$"_s );
1454 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1456 const QString toolPart( papszTokens[j] );
1457 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1458 if ( !match.hasMatch() )
1462 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1464 CSLDestroy( papszTokens );
1467 styles.insert( tool.toLower(), toolParts );
1469 CSLDestroy( papszStyleString );
1477 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1479 const thread_local QRegularExpression sUnitRx = QRegularExpression( u
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$"_s );
1480 const QRegularExpressionMatch match = sUnitRx.match( size );
1481 if ( match.hasMatch() )
1483 value = match.captured( 1 ).toDouble();
1484 const QString unitString = match.captured( 2 );
1485 if ( unitString.compare(
"px"_L1, Qt::CaseInsensitive ) == 0 )
1489 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1490 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1492 value *= PX_TO_PT_FACTOR;
1495 else if ( unitString.compare(
"pt"_L1, Qt::CaseInsensitive ) == 0 )
1500 else if ( unitString.compare(
"mm"_L1, Qt::CaseInsensitive ) == 0 )
1505 else if ( unitString.compare(
"cm"_L1, Qt::CaseInsensitive ) == 0 )
1511 else if ( unitString.compare(
"in"_L1, Qt::CaseInsensitive ) == 0 )
1516 else if ( unitString.compare(
'g'_L1, Qt::CaseInsensitive ) == 0 )
1525 QgsDebugError( u
"Could not parse style size %1"_s.arg( size ) );
1530 auto convertColor = [](
const QString & string ) -> QColor
1532 if (
string.isEmpty() )
1535 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( u
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$"_s );
1536 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1537 if ( match.hasMatch() )
1540 return QColor( u
"#%1%2"_s.arg( match.captured( 2 ), match.captured( 1 ) ) );
1544 return QColor(
string );
1548 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1550 QColor color = convertColor( lineStyle.value( u
"c"_s, u
"#000000"_s ).toString() );
1554 convertSize( lineStyle.value( u
"w"_s ).toString(), lineWidth, lineWidthUnit );
1557 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-pen-(\\d+)"_s );
1558 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1559 if ( match.hasMatch() )
1561 const int penId = match.captured( 1 ).toInt();
1568 auto simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1569 simpleLine->setWidthUnit( lineWidthUnit );
1572 const QString pattern = lineStyle.value( u
"p"_s ).toString();
1573 if ( !pattern.isEmpty() )
1575 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( u
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$"_s );
1576 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1577 if ( match.hasMatch() )
1579 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1580 QVector< qreal > dashPattern;
1582 for (
const QString &val : patternValues )
1585 convertSize( val + match.captured( 2 ), length, patternUnits );
1586 dashPattern.push_back( length * lineWidth * 2 );
1589 simpleLine->setCustomDashVector( dashPattern );
1590 simpleLine->setCustomDashPatternUnit( patternUnits );
1591 simpleLine->setUseCustomDashPattern(
true );
1595 Qt::PenCapStyle capStyle = Qt::FlatCap;
1596 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1598 const QString
id = lineStyle.value( u
"id"_s ).toString();
1599 if (
id.contains(
"mapinfo-pen"_L1, Qt::CaseInsensitive ) )
1604 capStyle = Qt::RoundCap;
1605 joinStyle = Qt::RoundJoin;
1609 const QString penCap = lineStyle.value( u
"cap"_s ).toString();
1610 if ( penCap.compare(
'b'_L1, Qt::CaseInsensitive ) == 0 )
1612 capStyle = Qt::FlatCap;
1614 else if ( penCap.compare(
'r'_L1, Qt::CaseInsensitive ) == 0 )
1616 capStyle = Qt::RoundCap;
1618 else if ( penCap.compare(
'p'_L1, Qt::CaseInsensitive ) == 0 )
1620 capStyle = Qt::SquareCap;
1622 simpleLine->setPenCapStyle( capStyle );
1625 const QString penJoin = lineStyle.value( u
"j"_s ).toString();
1626 if ( penJoin.compare(
'm'_L1, Qt::CaseInsensitive ) == 0 )
1628 joinStyle = Qt::MiterJoin;
1630 else if ( penJoin.compare(
'r'_L1, Qt::CaseInsensitive ) == 0 )
1632 joinStyle = Qt::RoundJoin;
1634 else if ( penJoin.compare(
'b'_L1, Qt::CaseInsensitive ) == 0 )
1636 joinStyle = Qt::BevelJoin;
1638 simpleLine->setPenJoinStyle( joinStyle );
1640 const QString priority = lineStyle.value( u
"l"_s ).toString();
1641 if ( !priority.isEmpty() )
1643 simpleLine->setRenderingPass( priority.toInt() );
1645 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1648 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1650 const QColor foreColor = convertColor( brushStyle.value( u
"fc"_s, u
"#000000"_s ).toString() );
1651 const QColor backColor = convertColor( brushStyle.value( u
"bc"_s, QString() ).toString() );
1653 const QString
id = brushStyle.value( u
"id"_s ).toString();
1656 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-brush-(\\d+)"_s );
1657 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1658 if ( match.hasMatch() )
1660 const int brushId = match.captured( 1 ).toInt();
1667 const thread_local QRegularExpression sOgrId = QRegularExpression( u
"ogr-brush-(\\d+)"_s );
1668 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1670 Qt::BrushStyle style = Qt::SolidPattern;
1671 if ( ogrMatch.hasMatch() )
1673 const int brushId = ogrMatch.captured( 1 ).toInt();
1677 style = Qt::SolidPattern;
1681 style = Qt::NoBrush;
1685 style = Qt::HorPattern;
1689 style = Qt::VerPattern;
1693 style = Qt::FDiagPattern;
1697 style = Qt::BDiagPattern;
1701 style = Qt::CrossPattern;
1705 style = Qt::DiagCrossPattern;
1711 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1713 auto backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1714 backgroundFill->setLocked(
true );
1715 backgroundFill->setStrokeStyle( Qt::NoPen );
1716 layers << backgroundFill.release();
1719 auto foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1720 foregroundFill->setBrushStyle( style );
1721 foregroundFill->setStrokeStyle( Qt::NoPen );
1723 const QString priority = brushStyle.value( u
"l"_s ).toString();
1724 if ( !priority.isEmpty() )
1726 foregroundFill->setRenderingPass( priority.toInt() );
1728 layers << foregroundFill.release();
1729 return std::make_unique< QgsFillSymbol >( layers );
1732 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1734 const QColor color = convertColor( symbolStyle.value( u
"c"_s, u
"#000000"_s ).toString() );
1738 convertSize( symbolStyle.value( u
"s"_s ).toString(), symbolSize, symbolSizeUnit );
1740 const double angle = symbolStyle.value( u
"a"_s, u
"0"_s ).toDouble();
1742 const QString
id = symbolStyle.value( u
"id"_s ).toString();
1745 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-sym-(\\d+)"_s );
1746 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1747 if ( match.hasMatch() )
1749 const int symbolId = match.captured( 1 ).toInt();
1760 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1762 const thread_local QRegularExpression sFontId = QRegularExpression( u
"font-sym-(\\d+)"_s );
1763 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1764 if ( fontMatch.hasMatch() )
1766 const int symId = fontMatch.captured( 1 ).toInt();
1767 const QStringList families = symbolStyle.value( u
"f"_s, QString() ).toString().split(
',' );
1769 bool familyFound =
false;
1772 for (
const QString &family : std::as_const( families ) )
1780 fontFamily = processedFamily;
1787 auto fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1788 fontMarker->setSizeUnit( symbolSizeUnit );
1789 fontMarker->setAngle( -angle );
1791 fontMarker->setColor( color );
1793 const QColor strokeColor = convertColor( symbolStyle.value( u
"o"_s, QString() ).toString() );
1794 if ( strokeColor.isValid() )
1796 fontMarker->setStrokeColor( strokeColor );
1797 fontMarker->setStrokeWidth( 1 );
1802 fontMarker->setStrokeWidth( 0 );
1805 markerLayer = std::move( fontMarker );
1807 else if ( !families.empty() )
1816 const thread_local QRegularExpression sOgrId = QRegularExpression( u
"ogr-sym-(\\d+)"_s );
1817 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1820 bool isFilled =
true;
1821 if ( ogrMatch.hasMatch() )
1823 const int symId = ogrMatch.captured( 1 ).toInt();
1886 auto simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
1887 simpleMarker->setSizeUnit( symbolSizeUnit );
1888 simpleMarker->setStrokeWidth( 1.0 );
1893 simpleMarker->setColor( color );
1894 simpleMarker->setStrokeStyle( Qt::NoPen );
1898 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1899 simpleMarker->setStrokeColor( color );
1902 const QColor strokeColor = convertColor( symbolStyle.value( u
"o"_s, QString() ).toString() );
1903 if ( strokeColor.isValid() )
1905 simpleMarker->setStrokeColor( strokeColor );
1906 simpleMarker->setStrokeStyle( Qt::SolidLine );
1909 markerLayer = std::move( simpleMarker );
1912 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1918 if ( styles.contains( u
"symbol"_s ) )
1920 const QVariantMap symbolStyle = styles.value( u
"symbol"_s ).toMap();
1921 return convertSymbol( symbolStyle );
1929 if ( styles.contains( u
"pen"_s ) )
1932 const QVariantMap lineStyle = styles.value( u
"pen"_s ).toMap();
1933 return convertPen( lineStyle );
1942 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1943 if ( styles.contains( u
"brush"_s ) )
1945 const QVariantMap brushStyle = styles.value( u
"brush"_s ).toMap();
1946 fillSymbol = convertBrush( brushStyle );
1950 auto emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1951 emptyFill->setBrushStyle( Qt::NoBrush );
1952 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1955 std::unique_ptr< QgsSymbol > penSymbol;
1956 if ( styles.contains( u
"pen"_s ) )
1958 const QVariantMap lineStyle = styles.value( u
"pen"_s ).toMap();
1959 penSymbol = convertPen( lineStyle );
1964 const int count = penSymbol->symbolLayerCount();
1974 for (
int i = 0; i < count; ++i )
1976 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1977 layer->setLocked(
true );
1978 fillSymbol->appendSymbolLayer( layer.release() );
1994 variantType = QMetaType::Type::UnknownType;
1995 variantSubType = QMetaType::Type::UnknownType;
2000 if ( ogrSubType == OFSTBoolean )
2002 variantType = QMetaType::Type::Bool;
2005 variantType = QMetaType::Type::Int;
2008 variantType = QMetaType::Type::LongLong;
2011 variantType = QMetaType::Type::Double;
2014 variantType = QMetaType::Type::QDate;
2017 variantType = QMetaType::Type::QTime;
2020 variantType = QMetaType::Type::QDateTime;
2024 variantType = QMetaType::Type::QByteArray;
2029 if ( ogrSubType == OFSTJSON )
2031 variantType = QMetaType::Type::QVariantMap;
2032 variantSubType = QMetaType::Type::QString;
2036 variantType = QMetaType::Type::QString;
2041 case OFTWideStringList:
2042 variantType = QMetaType::Type::QStringList;
2043 variantSubType = QMetaType::Type::QString;
2046 case OFTIntegerList:
2047 variantType = QMetaType::Type::QVariantList;
2048 variantSubType = QMetaType::Type::Int;
2052 variantType = QMetaType::Type::QVariantList;
2053 variantSubType = QMetaType::Type::Double;
2056 case OFTInteger64List:
2057 variantType = QMetaType::Type::QVariantList;
2058 variantSubType = QMetaType::Type::LongLong;
2065 ogrSubType = OFSTNone;
2066 switch ( variantType )
2068 case QMetaType::Type::Bool:
2069 ogrType = OFTInteger;
2070 ogrSubType = OFSTBoolean;
2073 case QMetaType::Type::Int:
2074 ogrType = OFTInteger;
2077 case QMetaType::Type::LongLong:
2078 ogrType = OFTInteger64;
2081 case QMetaType::Type::Double:
2085 case QMetaType::Type::QChar:
2086 case QMetaType::Type::QString:
2087 ogrType = OFTString;
2090 case QMetaType::Type::QStringList:
2091 ogrType = OFTStringList;
2094 case QMetaType::Type::QByteArray:
2095 ogrType = OFTBinary;
2098 case QMetaType::Type::QDate:
2102 case QMetaType::Type::QTime:
2105 case QMetaType::Type::QDateTime:
2106 ogrType = OFTDateTime;
2110 ogrType = OFTString;
2117 if (
string.isEmpty() )
2125 res =
string.toInt( &ok );
2129 res =
string.toLongLong( &ok );
2133 res =
string.toDouble( &ok );
2143 res = QDate::fromString(
string, Qt::ISODate );
2148 res = QTime::fromString(
string, Qt::ISODate );
2153 res = QDateTime::fromString(
string, Qt::ISODate );
2163 return ok ? res : QVariant();
2171 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2173 int nMaxIntLen = 11;
2174 int nMaxInt64Len = 21;
2175 int nMaxDoubleLen = 20;
2176 int nMaxDoublePrec = 15;
2178 if ( driverName ==
"GPKG"_L1 )
2188 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2195 if ( driverName ==
"GPKG"_L1 )
2196 nativeTypes <<
QgsVectorDataProvider::NativeType( QObject::tr(
"JSON (string)" ), u
"JSON"_s, QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
2198 bool supportsDate =
true;
2199 bool supportsTime =
true;
2200 bool supportsDateTime =
true;
2201 bool supportsBinary =
false;
2202 bool supportIntegerList =
false;
2203 bool supportInteger64List =
false;
2204 bool supportRealList =
false;
2205 bool supportsStringList =
false;
2209 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2211 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2212 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2213 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2214 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2215 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2216 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2217 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2218 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2219 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2220 CSLDestroy( papszTokens );
2225#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2226 if ( driverName ==
"ESRI Shapefile"_L1 )
2228 supportsDateTime =
false;
2242 if ( supportsDateTime )
2247 if ( supportsBinary )
2252 if ( supportIntegerList )
2257 if ( supportInteger64List )
2262 if ( supportRealList )
2267 if ( supportsStringList )
2273 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2274 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2285#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2291 const QString name{ OGR_FldDomain_GetName( domain ) };
2292 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2294 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
2295 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
2296 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2297 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2300 std::unique_ptr< QgsFieldDomain > res;
2301 switch ( OGR_FldDomain_GetDomainType( domain ) )
2305 QList< QgsCodedValue > values;
2306 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2307 while ( codedValue && codedValue->pszCode )
2309 const QString code( codedValue->pszCode );
2314 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2320 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2327 bool minIsInclusive =
false;
2328 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2333 bool maxIsInclusive =
false;
2334 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2339 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2340 minValue, minIsInclusive,
2341 maxValue, maxIsInclusive );
2346 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2347 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2351 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2353 case OFDMP_DEFAULT_VALUE:
2359 case OFDMP_GEOMETRY_WEIGHTED:
2364 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2366 case OFDSP_DEFAULT_VALUE:
2369 case OFDSP_DUPLICATE:
2372 case OFDSP_GEOMETRY_RATIO:
2384 OGRFieldType domainFieldType = OFTInteger;
2385 OGRFieldSubType domainFieldSubType = OFSTNone;
2388 OGRFieldDomainH res =
nullptr;
2389 switch ( domain->
type() )
2393 std::vector< OGRCodedValue > enumeration;
2394 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2395 enumeration.reserve( values.size() );
2398 OGRCodedValue codedValue;
2399 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2400 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2401 enumeration.push_back( codedValue );
2404 last.pszCode =
nullptr;
2405 last.pszValue =
nullptr;
2406 enumeration.push_back( last );
2407 res = OGR_CodedFldDomain_Create(
2408 domain->
name().toUtf8().constData(),
2415 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2417 CPLFree( value.pszCode );
2418 CPLFree( value.pszValue );
2425 std::unique_ptr< OGRField > min =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2426 std::unique_ptr< OGRField > max =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2429 res = OGR_RangeFldDomain_Create(
2430 domain->
name().toUtf8().constData(),
2435 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2437 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2444 res = OGR_GlobFldDomain_Create(
2445 domain->
name().toUtf8().constData(),
2449 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2458 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2461 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2464 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2479 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2482 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2485 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2498#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2502 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2504 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2506 QVariantMap leftTableUriParts = datasetUriParts;
2507 leftTableUriParts.insert( u
"layerName"_s, leftTableName );
2508 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2510 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2511 QVariantMap rightTableUriParts = datasetUriParts;
2512 rightTableUriParts.insert( u
"layerName"_s, rightTableName );
2513 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2515 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2516 QString mappingTableSource;
2517 if ( !mappingTableName.isEmpty() )
2519 QVariantMap mappingTableUriParts = datasetUriParts;
2520 mappingTableUriParts.insert( u
"layerName"_s, mappingTableName );
2521 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2524 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2526 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2528 CSLDestroy( cslLeftTableFieldNames );
2530 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2532 CSLDestroy( cslRightTableFieldNames );
2534 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2536 CSLDestroy( cslLeftMappingTableFieldNames );
2538 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2540 CSLDestroy( cslRightMappingTableFieldNames );
2542 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2543 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2544 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2546 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2548 switch ( relationshipType )
2554 case GRT_ASSOCIATION:
2558 case GRT_AGGREGATION:
2559 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2563 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2565 switch ( eCardinality )
2567 case GRC_ONE_TO_ONE:
2570 case GRC_ONE_TO_MANY:
2573 case GRC_MANY_TO_ONE:
2576 case GRC_MANY_TO_MANY:
2581 switch ( cardinality )
2590 QString(), QString(), rightTableSource, u
"ogr"_s,
2591 QString(), QString(), leftTableSource, u
"ogr"_s );
2606 QString(), QString(), rightTableSource, u
"ogr"_s,
2607 QString(), QString(), leftTableSource, u
"ogr"_s );
2625 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2629 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2632 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2635 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2638 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2645 const QString leftTableName = leftParts.value( u
"layerName"_s ).toString();
2646 if ( leftTableName.isEmpty() )
2648 error = QObject::tr(
"Parent table name was not set" );
2653 const QString rightTableName = rightParts.value( u
"layerName"_s ).toString();
2654 if ( rightTableName.isEmpty() )
2656 error = QObject::tr(
"Child table name was not set" );
2660 if ( leftParts.value( u
"path"_s ).toString() != rightParts.value( u
"path"_s ).toString() )
2662 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2666 QString mappingTableName;
2670 mappingTableName = mappingParts.value( u
"layerName"_s ).toString();
2671 if ( leftParts.value( u
"path"_s ).toString() != mappingParts.value( u
"path"_s ).toString() )
2673 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2679 leftTableName.toLocal8Bit().constData(),
2680 rightTableName.toLocal8Bit().constData(),
2685 int count = leftFieldNames.count();
2686 char **lst =
nullptr;
2689 for (
const QString &
string : leftFieldNames )
2691 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2694 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2699 count = rightFieldNames.count();
2703 for (
const QString &
string : rightFieldNames )
2705 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2708 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2711 if ( !mappingTableName.isEmpty() )
2713 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2717 int count = leftFieldNames.count();
2721 for (
const QString &
string : leftFieldNames )
2723 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2726 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2731 count = rightFieldNames.count();
2735 for (
const QString &
string : rightFieldNames )
2737 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2740 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2748 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2752 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2758 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2760 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2764 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2772 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2776 errCause = QObject::tr(
"No styles available on DB" );
2780 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2783 errCause = QObject::tr(
"No styles available on DB" );
2787 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2789 OGR_L_ResetReading( hLayer );
2791 QList<qlonglong> listTimestamp;
2792 QMap<int, QString> mapIdToStyleName;
2793 QMap<int, QString> mapIdToDescription;
2794 QMap<qlonglong, QList<int> > mapTimestampToId;
2795 int numberOfRelatedStyles = 0;
2803 QString tableName( QString::fromUtf8(
2804 OGR_F_GetFieldAsString( hFeature.get(),
2805 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2806 QString geometryColumn( QString::fromUtf8(
2807 OGR_F_GetFieldAsString( hFeature.get(),
2808 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2809 QString styleName( QString::fromUtf8(
2810 OGR_F_GetFieldAsString( hFeature.get(),
2811 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2812 QString description( QString::fromUtf8(
2813 OGR_F_GetFieldAsString( hFeature.get(),
2814 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2815 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2816 if ( tableName == layerName &&
2817 geometryColumn == geomColumn )
2820 QString id( QString::number( fid ) );
2822 names.append( styleName );
2823 descriptions.append( description );
2824 ++ numberOfRelatedStyles;
2828 int year, month, day, hour, minute, second, TZ;
2829 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2830 &year, &month, &day, &hour, &minute, &second, &TZ );
2831 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2832 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2834 listTimestamp.append( ts );
2835 mapIdToStyleName[fid] = styleName;
2836 mapIdToDescription[fid] = description;
2837 mapTimestampToId[ts].append( fid );
2841 std::sort( listTimestamp.begin(), listTimestamp.end() );
2843 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2845 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2846 for (
int j = 0; j < listId.size(); j++ )
2848 int fid = listId[j];
2849 QString id( QString::number( fid ) );
2851 names.append( mapIdToStyleName[fid] );
2852 descriptions.append( mapIdToDescription[fid] );
2856 return numberOfRelatedStyles;
2864 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2868 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2870 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2871 " AND f_table_name=%1"
2872 " AND f_geometry_column=%2"
2873 " AND styleName=%3" )
2874 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2875 QgsOgrProviderUtils::quotedValue( geomColumn ),
2876 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2877 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2878 OGR_L_ResetReading( hLayer );
2880 OGR_L_ResetReading( hLayer );
2890 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2894 errCause = QObject::tr(
"No styles available on DB" );
2899 int id = styleId.toInt( &ok );
2902 errCause = QObject::tr(
"Invalid style identifier" );
2909 errCause = QObject::tr(
"No style corresponding to style identifier" );
2913 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2914 QString styleQML( QString::fromUtf8(
2915 OGR_F_GetFieldAsString( hFeature.get(),
2916 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2917 OGR_L_ResetReading( hLayer );
2926 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2931 errCause = QObject::tr(
"Connection to database failed" );
2936 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2938 errCause = QObject::tr(
"Error executing the delete query." );
2951 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2955 errCause = QObject::tr(
"No styles available on DB" );
2959 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2960 " AND f_table_name=%1"
2961 " AND f_geometry_column=%2"
2962 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2963 ",update_time DESC" )
2964 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2965 QgsOgrProviderUtils::quotedValue( geomColumn ) );
2966 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2967 OGR_L_ResetReading( hLayer );
2968 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2970 qlonglong moreRecentTimestamp = 0;
2976 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2978 styleQML = QString::fromUtf8(
2979 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2980 styleName = QString::fromUtf8(
2981 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2985 int year, month, day, hour, minute, second, TZ;
2986 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2987 &year, &month, &day, &hour, &minute, &second, &TZ );
2988 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2989 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2990 if ( ts > moreRecentTimestamp )
2992 moreRecentTimestamp = ts;
2993 styleQML = QString::fromUtf8(
2994 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2995 styleName = QString::fromUtf8(
2996 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2999 OGR_L_ResetReading( hLayer );
3005 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
3006 const QString &styleName,
const QString &styleDescription,
3007 const QString &uiFileContent,
bool useAsDefault, QString &errCause
3011 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
3018 char **options =
nullptr;
3020 options = CSLSetNameValue( options,
"FID",
"id" );
3021 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
3022 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
3023 CSLDestroy( options );
3026 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
3032 OGR_Fld_SetWidth( fld.get(), 256 );
3033 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3037 OGR_Fld_SetWidth( fld.get(), 256 );
3038 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3042 OGR_Fld_SetWidth( fld.get(), 256 );
3043 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3047 OGR_Fld_SetWidth( fld.get(), 256 );
3048 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3052 OGR_Fld_SetWidth( fld.get(), 30 );
3053 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3057 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3061 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3065 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
3066 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3070 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3074 OGR_Fld_SetWidth( fld.get(), 30 );
3075 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3079 OGR_Fld_SetWidth( fld.get(), 30 );
3080 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3084 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
3085 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
3089 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
3094 QString realStyleName =
3095 styleName.isEmpty() ? layerName : styleName;
3097 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
3101 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
3102 " AND f_table_name=%1"
3103 " AND f_geometry_column=%2" )
3104 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3105 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
3106 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
3110 OGR_F_SetFieldInteger( hFeature.get(),
3111 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3113 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
3116 QgsDebugError( u
"Could not unset previous useAsDefault style"_s );
3121 QString checkQuery = QStringLiteral(
"f_table_schema=''"
3122 " AND f_table_name=%1"
3123 " AND f_geometry_column=%2"
3124 " AND styleName=%3" )
3125 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3126 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
3127 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
3128 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
3129 OGR_L_ResetReading( hLayer );
3131 OGR_L_ResetReading( hLayer );
3140 hFeature.reset( OGR_F_Create( hLayerDefn ) );
3141 OGR_F_SetFieldString( hFeature.get(),
3142 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
3144 OGR_F_SetFieldString( hFeature.get(),
3145 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
3147 OGR_F_SetFieldString( hFeature.get(),
3148 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
3149 layerName.toUtf8().constData() );
3150 OGR_F_SetFieldString( hFeature.get(),
3151 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
3152 geomColumn.toUtf8().constData() );
3153 OGR_F_SetFieldString( hFeature.get(),
3154 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
3155 realStyleName.toUtf8().constData() );
3156 if ( !uiFileContent.isEmpty() )
3158 OGR_F_SetFieldString( hFeature.get(),
3159 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
3160 uiFileContent.toUtf8().constData() );
3163 OGR_F_SetFieldString( hFeature.get(),
3164 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3165 qmlStyle.toUtf8().constData() );
3166 OGR_F_SetFieldString( hFeature.get(),
3167 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3168 sldStyle.toUtf8().constData() );
3169 OGR_F_SetFieldInteger( hFeature.get(),
3170 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3171 useAsDefault ? 1 : 0 );
3172 OGR_F_SetFieldString( hFeature.get(),
3173 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3174 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3175 OGR_F_SetFieldString( hFeature.get(),
3176 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3181 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3183 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3188 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.
@ NurbsCurveM
NurbsCurveM.
@ MultiPolygon25D
MultiPolygon25D.
@ MultiPointM
MultiPointM.
@ LineStringZM
LineStringZM.
@ GeometryCollectionZM
GeometryCollectionZM.
@ CompoundCurveZM
CompoundCurveZM.
@ CompoundCurveM
CompoundCurveM.
@ MultiLineString25D
MultiLineString25D.
@ MultiPolygon
MultiPolygon.
@ GeometryCollectionZ
GeometryCollectionZ.
@ GeometryCollectionM
GeometryCollectionM.
@ CircularStringZM
CircularStringZM.
@ MultiSurfaceZ
MultiSurfaceZ.
@ CurvePolygonZM
CurvePolygonZM.
@ MultiLineString
MultiLineString.
@ MultiPolygonM
MultiPolygonM.
@ MultiCurveZM
MultiCurveZM.
@ MultiSurfaceZM
MultiSurfaceZM.
@ MultiPoint25D
MultiPoint25D.
@ NurbsCurveZ
NurbsCurveZ.
@ CurvePolygonM
CurvePolygonM.
@ NurbsCurveZM
NurbsCurveZM.
@ 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 QStringList cStringListToQStringList(const char *const *stringList)
Converts a c string list to a QStringList.
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
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 OGRwkbGeometryType qgsWkbTypeToOgrGeometryType(Qgis::WkbType wkbType, bool approx=false)
Converts a QgsWkbTypes::Type to a OGRwkbGeometryType.
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< QgsPolyhedralSurface > ogrGeometryToQgsPolyhedralSurface(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.