38#include "qgsogrproviderutils.h"
46using namespace Qt::StringLiterals;
48#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
59#include <QJsonDocument>
64#include <QRegularExpression>
66#include "ogr_srs_api.h"
68#include "nlohmann/json.hpp"
72 OGR_DS_Destroy( source );
78 OGR_G_DestroyGeometry( geometry );
83 OGR_Fld_Destroy( definition );
88 OGR_F_Destroy( feature );
105 CPLPushErrorHandler( CPLQuietErrorHandler );
106 GDALDeleteDataset( driver, path.toUtf8().constData() );
107 CPLPopErrorHandler();
118 GDALDestroyWarpOptions( options );
121#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
124 GDALDestroyRelationship( relationship );
128static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt,
int nTZFlag )
135 else if ( nTZFlag == 1 )
137 dt.setTimeSpec( Qt::LocalTime );
139 else if ( nTZFlag == 100 )
141 dt.setTimeSpec( Qt::UTC );
147 dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
153 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
159 return value->Integer;
162 return value->Integer64;
169 return QString::fromUtf8( value->String );
172 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
176 float secondsPart = 0;
177 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
178 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
183 float secondsPart = 0;
184 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
185 QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
186 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
187 setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
193 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
199 res.reserve( value->IntegerList.nCount );
200 for (
int i = 0; i < value->IntegerList.nCount; ++i )
201 res << value->IntegerList.paList[ i ];
205 case OFTInteger64List:
208 res.reserve( value->Integer64List.nCount );
209 for (
int i = 0; i < value->Integer64List.nCount; ++i )
210 res << value->Integer64List.paList[ i ];
217 res.reserve( value->RealList.nCount );
218 for (
int i = 0; i < value->RealList.nCount; ++i )
219 res << value->RealList.paList[ i ];
224 case OFTWideStringList:
227 res.reserve( value->StringList.nCount );
228 for (
int i = 0; i < value->StringList.nCount; ++i )
229 res << QString::fromUtf8( value->StringList.paList[ i ] );
238 if ( datetime.timeSpec() == Qt::LocalTime )
240 return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
245 auto res = std::make_unique< OGRField >();
247 switch ( value.userType() )
249 case QMetaType::Type::UnknownType:
250 OGR_RawField_SetUnset( res.get() );
252 case QMetaType::Type::Bool:
254 const int val = value.toBool() ? 1 : 0;
255 if ( type == OFTInteger )
257 else if ( type == OFTInteger64 )
258 res->Integer64 = val;
259 else if ( type == OFTReal )
268 case QMetaType::Type::Int:
270 const int val = value.toInt();
271 if ( type == OFTInteger )
273 else if ( type == OFTInteger64 )
274 res->Integer64 = val;
275 else if ( type == OFTReal )
284 case QMetaType::Type::LongLong:
286 const qint64 val = value.toLongLong();
287 if ( type == OFTInteger )
289 if ( val <= std::numeric_limits<int>::max() &&
290 val >= std::numeric_limits<int>::min() )
292 res->Integer =
static_cast<int>( val );
300 else if ( type == OFTInteger64 )
301 res->Integer64 = val;
302 else if ( type == OFTReal )
304 res->Real =
static_cast<double>( val );
308 QgsDebugError(
"Unsupported output data type for LongLong" );
313 case QMetaType::Type::Double:
315 double val = value.toDouble();
316 if ( type == OFTInteger )
318 if ( val <= std::numeric_limits<int>::max() &&
319 val >= std::numeric_limits<int>::min() )
321 res->Integer =
static_cast<int>( val );
329 else if ( type == OFTInteger64 )
331 if ( val <=
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
332 val >=
static_cast<double>( std::numeric_limits<qint64>::min() ) )
334 res->Integer64 =
static_cast<qint64
>( val );
342 else if ( type == OFTReal )
348 QgsDebugError(
"Unsupported output data type for LongLong" );
353 case QMetaType::Type::QChar:
354 case QMetaType::Type::QString:
356 if ( type == OFTString )
357 res->String = CPLStrdup( value.toString().toUtf8().constData() );
365 case QMetaType::Type::QDate:
367 if ( type == OFTDate )
369 const QDate date = value.toDate();
370 res->Date.Day = date.day();
371 res->Date.Month = date.month();
372 res->Date.Year =
static_cast<GInt16
>( date.year() );
373 res->Date.TZFlag = 0;
382 case QMetaType::Type::QTime:
384 if ( type == OFTTime )
386 const QTime time = value.toTime();
387 res->Date.Hour = time.hour();
388 res->Date.Minute = time.minute();
389 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
390 res->Date.TZFlag = 0;
399 case QMetaType::Type::QDateTime:
401 if ( type == OFTDateTime )
403 const QDateTime dt = value.toDateTime();
404 const QDate date = dt.date();
405 res->Date.Day = date.day();
406 res->Date.Month = date.month();
407 res->Date.Year =
static_cast<GInt16
>( date.year() );
408 const QTime time = dt.time();
409 res->Date.Hour = time.hour();
410 res->Date.Minute = time.minute();
411 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
416 QgsDebugError(
"Unsupported output data type for DateTime" );
423 QgsDebugError(
"Unhandled variant type in variantToOGRField" );
424 OGR_RawField_SetUnset( res.get() );
440 feature.
setId( OGR_F_GetFID( ogrFet ) );
463 int fieldCount = OGR_F_GetFieldCount( ogrFet );
464 for (
int i = 0; i < fieldCount; ++i )
466 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
473 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
474 QMetaType::Type varType;
475 switch ( OGR_Fld_GetType( fldDef ) )
478 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
479 varType = QMetaType::Type::Bool;
481 varType = QMetaType::Type::Int;
484 varType = QMetaType::Type::LongLong;
487 varType = QMetaType::Type::Double;
490 varType = QMetaType::Type::QDate;
493 varType = QMetaType::Type::QTime;
496 varType = QMetaType::Type::QDateTime;
499 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
500 varType = QMetaType::Type::QVariantMap;
502 varType = QMetaType::Type::QString;
505 varType = QMetaType::Type::QString;
515 if ( attIndex < 0 || attIndex >= fields.
count() )
528 if ( !ogrFet || attIndex < 0 )
535 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
542 QgsDebugError( u
"ogrFet->GetFieldDefnRef(attindex) returns NULL"_s );
552 auto getJsonValue = [&]() ->
bool
554 const char *json = OGR_F_GetFieldAsString( ogrFet, attIndex );
557 jsonContent = encoding->toUnicode( json ).toUtf8();
559 jsonContent = QString::fromUtf8( json ).toUtf8();
563 const nlohmann::json json_element = json::parse( jsonContent.toStdString() );
567 catch (
const json::parse_error &e )
574 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
576 switch ( field.
type() )
578 case QMetaType::Type::QString:
580 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
583 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
585 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
590 if ( value.isNull() )
591 value = QVariant( u
""_s );
596 case QMetaType::Type::Int:
597 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
599 case QMetaType::Type::Bool:
600 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
602 case QMetaType::Type::LongLong:
603 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
605 case QMetaType::Type::Double:
606 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
608 case QMetaType::Type::QDate:
609 case QMetaType::Type::QDateTime:
610 case QMetaType::Type::QTime:
612 int year, month, day, hour, minute, tzf;
614 float secondsPart = 0;
616 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
617 float millisecondPart = std::modf( second, &secondsPart );
619 if ( field.
type() == QMetaType::Type::QDate )
620 value = QDate( year, month, day );
621 else if ( field.
type() == QMetaType::Type::QTime )
622 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
625 QDateTime dt = QDateTime( QDate( year, month, day ),
626 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
627 setQTTimeZoneFromOGRTZFlag( dt, tzf );
633 case QMetaType::Type::QByteArray:
636 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
640 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
647 case QMetaType::Type::QStringList:
649 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
652 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
653 const int count = CSLCount( lst );
656 list.reserve( count );
657 for (
int i = 0; i < count; i++ )
660 list << encoding->toUnicode( lst[i] );
662 list << QString::fromUtf8( lst[i] );
670 case QMetaType::Type::QVariantList:
674 case QMetaType::Type::QString:
676 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
679 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
680 const int count = CSLCount( lst );
683 list.reserve( count );
684 for (
int i = 0; i < count; i++ )
687 list << encoding->toUnicode( lst[i] );
689 list << QString::fromUtf8( lst[i] );
697 case QMetaType::Type::Int:
699 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
703 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
706 list.reserve( count );
707 for (
int i = 0; i < count; i++ )
717 case QMetaType::Type::Double:
719 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
723 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
726 list.reserve( count );
727 for (
int i = 0; i < count; i++ )
737 case QMetaType::Type::LongLong:
739 if ( field.
typeName() !=
"JSON"_L1 || ! getJsonValue() )
743 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
746 list.reserve( count );
747 for (
int i = 0; i < count; i++ )
759 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
768 case QMetaType::Type::QVariantMap:
773 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
775 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
779 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
802 for (
int idx = 0; idx < fields.
count(); ++idx )
818 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
832 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
833 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
838 auto mp = std::make_unique< QgsMultiPoint >();
840 const int count = OGR_G_GetGeometryCount( geom );
841 mp->reserve( count );
842 for (
int i = 0; i < count; ++i )
854 int count = OGR_G_GetPointCount( geom );
855 QVector< double > x( count );
856 QVector< double > y( count );
858 double *pz =
nullptr;
864 double *pm =
nullptr;
871 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
878 auto mp = std::make_unique< QgsMultiLineString >();
880 const int count = OGR_G_GetGeometryCount( geom );
881 mp->reserve( count );
882 for (
int i = 0; i < count; ++i )
892 auto polygon = std::make_unique< QgsPolygon >();
894 const int count = OGR_G_GetGeometryCount( geom );
900 for (
int i = 1; i < count; ++i )
910 auto polygon = std::make_unique< QgsMultiPolygon >();
912 const int count = OGR_G_GetGeometryCount( geom );
913 polygon->reserve( count );
914 for (
int i = 0; i < count; ++i )
924 switch ( ogrGeomType )
1013 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
1056 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
1059 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
1060 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
1062 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
1064 OGR_G_DestroyGeometry( newGeom );
1070 int memorySize = OGR_G_WkbSize( geom );
1071 unsigned char *wkb =
new unsigned char[memorySize];
1082 if (
string.isEmpty() )
1085 QString randomFileName = u
"/vsimem/%1"_s.arg( QUuid::createUuid().toString() );
1088 QByteArray ba =
string.toUtf8();
1089 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1090 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1095 VSIUnlink( randomFileName.toUtf8().constData() );
1099 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1103 VSIUnlink( randomFileName.toUtf8().constData() );
1108 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1116 VSIUnlink( randomFileName.toUtf8().constData() );
1124 if (
string.isEmpty() )
1127 QString randomFileName = u
"/vsimem/%1"_s.arg( QUuid::createUuid().toString() );
1130 QByteArray ba =
string.toUtf8();
1131 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1132 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1137 VSIUnlink( randomFileName.toUtf8().constData() );
1141 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1145 VSIUnlink( randomFileName.toUtf8().constData() );
1151 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1157 VSIUnlink( randomFileName.toUtf8().constData() );
1166 QStringList strings;
1168 for (
qgssize i = 0; stringList[i]; ++i )
1170 strings.append( QString::fromUtf8( stringList[i] ) );
1181 char *pszWkt =
nullptr;
1182 const QByteArray multiLineOption = u
"MULTILINE=NO"_s.toLocal8Bit();
1183 const QByteArray formatOption = u
"FORMAT=WKT2"_s.toLocal8Bit();
1184 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1185 OSRExportToWktEx( srs, &pszWkt, options );
1187 const QString res( pszWkt );
1195 if ( wkt.isEmpty() )
1198 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1199 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1201 if ( authorityName && authorityCode )
1203 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1204 OGRSpatialReferenceH ogrSrsTmp = OSRNewSpatialReference(
nullptr );
1206 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1207 OSRIsSame( srs, ogrSrsTmp ) )
1212 OSRDestroySpatialReference( ogrSrsTmp );
1217#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1218 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1219 if ( coordinateEpoch > 0 )
1229 OGRSpatialReferenceH ogrSrs =
nullptr;
1235 const QString authId = crs.
authid();
1237 if ( !authId.isEmpty() )
1239 ogrSrs = OSRNewSpatialReference(
nullptr );
1240 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1243 OGRSpatialReferenceH ogrSrsFromWkt = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1244 if ( ogrSrsFromWkt )
1246 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1248 OSRDestroySpatialReference( ogrSrs );
1249 ogrSrs = ogrSrsFromWkt;
1253 OSRDestroySpatialReference( ogrSrsFromWkt );
1259 OSRDestroySpatialReference( ogrSrs );
1265 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1269 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1270#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1286 if ( !cpgEncoding.isEmpty() )
1295 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1296 return layer ? layer->GetMetadataItem( u
"ENCODING_FROM_CPG"_s, u
"SHAPEFILE"_s ) : QString();
1302 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1303 return layer ? layer->GetMetadataItem( u
"ENCODING_FROM_LDID"_s, u
"SHAPEFILE"_s ) : QString();
1310 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1312 | CSLT_PRESERVEQUOTES
1313 | CSLT_PRESERVEESCAPES );
1314 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1320 const thread_local QRegularExpression sToolPartRx( u
"^(.*?)\\((.*)\\)$"_s );
1321 const QString stylePart( papszStyleString[i] );
1322 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1323 if ( !match.hasMatch() )
1326 const QString tool = match.captured( 1 );
1327 const QString params = match.captured( 2 );
1329 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1330 | CSLT_PRESERVEESCAPES );
1332 QVariantMap toolParts;
1333 const thread_local QRegularExpression sToolParamRx( u
"^(.*?):(.*)$"_s );
1334 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1336 const QString toolPart( papszTokens[j] );
1337 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1338 if ( !match.hasMatch() )
1342 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1344 CSLDestroy( papszTokens );
1347 styles.insert( tool.toLower(), toolParts );
1349 CSLDestroy( papszStyleString );
1357 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1359 const thread_local QRegularExpression sUnitRx = QRegularExpression( u
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$"_s );
1360 const QRegularExpressionMatch match = sUnitRx.match( size );
1361 if ( match.hasMatch() )
1363 value = match.captured( 1 ).toDouble();
1364 const QString unitString = match.captured( 2 );
1365 if ( unitString.compare(
"px"_L1, Qt::CaseInsensitive ) == 0 )
1369 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1370 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1372 value *= PX_TO_PT_FACTOR;
1375 else if ( unitString.compare(
"pt"_L1, Qt::CaseInsensitive ) == 0 )
1380 else if ( unitString.compare(
"mm"_L1, Qt::CaseInsensitive ) == 0 )
1385 else if ( unitString.compare(
"cm"_L1, Qt::CaseInsensitive ) == 0 )
1391 else if ( unitString.compare(
"in"_L1, Qt::CaseInsensitive ) == 0 )
1396 else if ( unitString.compare(
'g'_L1, Qt::CaseInsensitive ) == 0 )
1405 QgsDebugError( u
"Could not parse style size %1"_s.arg( size ) );
1410 auto convertColor = [](
const QString & string ) -> QColor
1412 if (
string.isEmpty() )
1415 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( u
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$"_s );
1416 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1417 if ( match.hasMatch() )
1420 return QColor( u
"#%1%2"_s.arg( match.captured( 2 ), match.captured( 1 ) ) );
1424 return QColor(
string );
1428 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1430 QColor color = convertColor( lineStyle.value( u
"c"_s, u
"#000000"_s ).toString() );
1434 convertSize( lineStyle.value( u
"w"_s ).toString(), lineWidth, lineWidthUnit );
1437 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-pen-(\\d+)"_s );
1438 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1439 if ( match.hasMatch() )
1441 const int penId = match.captured( 1 ).toInt();
1448 auto simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1449 simpleLine->setWidthUnit( lineWidthUnit );
1452 const QString pattern = lineStyle.value( u
"p"_s ).toString();
1453 if ( !pattern.isEmpty() )
1455 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( u
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$"_s );
1456 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1457 if ( match.hasMatch() )
1459 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1460 QVector< qreal > dashPattern;
1462 for (
const QString &val : patternValues )
1465 convertSize( val + match.captured( 2 ), length, patternUnits );
1466 dashPattern.push_back( length * lineWidth * 2 );
1469 simpleLine->setCustomDashVector( dashPattern );
1470 simpleLine->setCustomDashPatternUnit( patternUnits );
1471 simpleLine->setUseCustomDashPattern(
true );
1475 Qt::PenCapStyle capStyle = Qt::FlatCap;
1476 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1478 const QString
id = lineStyle.value( u
"id"_s ).toString();
1479 if (
id.contains(
"mapinfo-pen"_L1, Qt::CaseInsensitive ) )
1484 capStyle = Qt::RoundCap;
1485 joinStyle = Qt::RoundJoin;
1489 const QString penCap = lineStyle.value( u
"cap"_s ).toString();
1490 if ( penCap.compare(
'b'_L1, Qt::CaseInsensitive ) == 0 )
1492 capStyle = Qt::FlatCap;
1494 else if ( penCap.compare(
'r'_L1, Qt::CaseInsensitive ) == 0 )
1496 capStyle = Qt::RoundCap;
1498 else if ( penCap.compare(
'p'_L1, Qt::CaseInsensitive ) == 0 )
1500 capStyle = Qt::SquareCap;
1502 simpleLine->setPenCapStyle( capStyle );
1505 const QString penJoin = lineStyle.value( u
"j"_s ).toString();
1506 if ( penJoin.compare(
'm'_L1, Qt::CaseInsensitive ) == 0 )
1508 joinStyle = Qt::MiterJoin;
1510 else if ( penJoin.compare(
'r'_L1, Qt::CaseInsensitive ) == 0 )
1512 joinStyle = Qt::RoundJoin;
1514 else if ( penJoin.compare(
'b'_L1, Qt::CaseInsensitive ) == 0 )
1516 joinStyle = Qt::BevelJoin;
1518 simpleLine->setPenJoinStyle( joinStyle );
1520 const QString priority = lineStyle.value( u
"l"_s ).toString();
1521 if ( !priority.isEmpty() )
1523 simpleLine->setRenderingPass( priority.toInt() );
1525 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1528 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1530 const QColor foreColor = convertColor( brushStyle.value( u
"fc"_s, u
"#000000"_s ).toString() );
1531 const QColor backColor = convertColor( brushStyle.value( u
"bc"_s, QString() ).toString() );
1533 const QString
id = brushStyle.value( u
"id"_s ).toString();
1536 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-brush-(\\d+)"_s );
1537 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1538 if ( match.hasMatch() )
1540 const int brushId = match.captured( 1 ).toInt();
1547 const thread_local QRegularExpression sOgrId = QRegularExpression( u
"ogr-brush-(\\d+)"_s );
1548 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1550 Qt::BrushStyle style = Qt::SolidPattern;
1551 if ( ogrMatch.hasMatch() )
1553 const int brushId = ogrMatch.captured( 1 ).toInt();
1557 style = Qt::SolidPattern;
1561 style = Qt::NoBrush;
1565 style = Qt::HorPattern;
1569 style = Qt::VerPattern;
1573 style = Qt::FDiagPattern;
1577 style = Qt::BDiagPattern;
1581 style = Qt::CrossPattern;
1585 style = Qt::DiagCrossPattern;
1591 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1593 auto backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1594 backgroundFill->setLocked(
true );
1595 backgroundFill->setStrokeStyle( Qt::NoPen );
1596 layers << backgroundFill.release();
1599 auto foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1600 foregroundFill->setBrushStyle( style );
1601 foregroundFill->setStrokeStyle( Qt::NoPen );
1603 const QString priority = brushStyle.value( u
"l"_s ).toString();
1604 if ( !priority.isEmpty() )
1606 foregroundFill->setRenderingPass( priority.toInt() );
1608 layers << foregroundFill.release();
1609 return std::make_unique< QgsFillSymbol >( layers );
1612 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1614 const QColor color = convertColor( symbolStyle.value( u
"c"_s, u
"#000000"_s ).toString() );
1618 convertSize( symbolStyle.value( u
"s"_s ).toString(), symbolSize, symbolSizeUnit );
1620 const double angle = symbolStyle.value( u
"a"_s, u
"0"_s ).toDouble();
1622 const QString
id = symbolStyle.value( u
"id"_s ).toString();
1625 const thread_local QRegularExpression sMapInfoId = QRegularExpression( u
"mapinfo-sym-(\\d+)"_s );
1626 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1627 if ( match.hasMatch() )
1629 const int symbolId = match.captured( 1 ).toInt();
1640 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1642 const thread_local QRegularExpression sFontId = QRegularExpression( u
"font-sym-(\\d+)"_s );
1643 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1644 if ( fontMatch.hasMatch() )
1646 const int symId = fontMatch.captured( 1 ).toInt();
1647 const QStringList families = symbolStyle.value( u
"f"_s, QString() ).toString().split(
',' );
1649 bool familyFound =
false;
1652 for (
const QString &family : std::as_const( families ) )
1660 fontFamily = processedFamily;
1667 auto fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1668 fontMarker->setSizeUnit( symbolSizeUnit );
1669 fontMarker->setAngle( -angle );
1671 fontMarker->setColor( color );
1673 const QColor strokeColor = convertColor( symbolStyle.value( u
"o"_s, QString() ).toString() );
1674 if ( strokeColor.isValid() )
1676 fontMarker->setStrokeColor( strokeColor );
1677 fontMarker->setStrokeWidth( 1 );
1682 fontMarker->setStrokeWidth( 0 );
1685 markerLayer = std::move( fontMarker );
1687 else if ( !families.empty() )
1696 const thread_local QRegularExpression sOgrId = QRegularExpression( u
"ogr-sym-(\\d+)"_s );
1697 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1700 bool isFilled =
true;
1701 if ( ogrMatch.hasMatch() )
1703 const int symId = ogrMatch.captured( 1 ).toInt();
1766 auto simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
1767 simpleMarker->setSizeUnit( symbolSizeUnit );
1768 simpleMarker->setStrokeWidth( 1.0 );
1773 simpleMarker->setColor( color );
1774 simpleMarker->setStrokeStyle( Qt::NoPen );
1778 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1779 simpleMarker->setStrokeColor( color );
1782 const QColor strokeColor = convertColor( symbolStyle.value( u
"o"_s, QString() ).toString() );
1783 if ( strokeColor.isValid() )
1785 simpleMarker->setStrokeColor( strokeColor );
1786 simpleMarker->setStrokeStyle( Qt::SolidLine );
1789 markerLayer = std::move( simpleMarker );
1792 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1798 if ( styles.contains( u
"symbol"_s ) )
1800 const QVariantMap symbolStyle = styles.value( u
"symbol"_s ).toMap();
1801 return convertSymbol( symbolStyle );
1809 if ( styles.contains( u
"pen"_s ) )
1812 const QVariantMap lineStyle = styles.value( u
"pen"_s ).toMap();
1813 return convertPen( lineStyle );
1822 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1823 if ( styles.contains( u
"brush"_s ) )
1825 const QVariantMap brushStyle = styles.value( u
"brush"_s ).toMap();
1826 fillSymbol = convertBrush( brushStyle );
1830 auto emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1831 emptyFill->setBrushStyle( Qt::NoBrush );
1832 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1835 std::unique_ptr< QgsSymbol > penSymbol;
1836 if ( styles.contains( u
"pen"_s ) )
1838 const QVariantMap lineStyle = styles.value( u
"pen"_s ).toMap();
1839 penSymbol = convertPen( lineStyle );
1844 const int count = penSymbol->symbolLayerCount();
1854 for (
int i = 0; i < count; ++i )
1856 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1857 layer->setLocked(
true );
1858 fillSymbol->appendSymbolLayer( layer.release() );
1874 variantType = QMetaType::Type::UnknownType;
1875 variantSubType = QMetaType::Type::UnknownType;
1880 if ( ogrSubType == OFSTBoolean )
1882 variantType = QMetaType::Type::Bool;
1885 variantType = QMetaType::Type::Int;
1888 variantType = QMetaType::Type::LongLong;
1891 variantType = QMetaType::Type::Double;
1894 variantType = QMetaType::Type::QDate;
1897 variantType = QMetaType::Type::QTime;
1900 variantType = QMetaType::Type::QDateTime;
1904 variantType = QMetaType::Type::QByteArray;
1909 if ( ogrSubType == OFSTJSON )
1911 variantType = QMetaType::Type::QVariantMap;
1912 variantSubType = QMetaType::Type::QString;
1916 variantType = QMetaType::Type::QString;
1921 case OFTWideStringList:
1922 variantType = QMetaType::Type::QStringList;
1923 variantSubType = QMetaType::Type::QString;
1926 case OFTIntegerList:
1927 variantType = QMetaType::Type::QVariantList;
1928 variantSubType = QMetaType::Type::Int;
1932 variantType = QMetaType::Type::QVariantList;
1933 variantSubType = QMetaType::Type::Double;
1936 case OFTInteger64List:
1937 variantType = QMetaType::Type::QVariantList;
1938 variantSubType = QMetaType::Type::LongLong;
1945 ogrSubType = OFSTNone;
1946 switch ( variantType )
1948 case QMetaType::Type::Bool:
1949 ogrType = OFTInteger;
1950 ogrSubType = OFSTBoolean;
1953 case QMetaType::Type::Int:
1954 ogrType = OFTInteger;
1957 case QMetaType::Type::LongLong:
1958 ogrType = OFTInteger64;
1961 case QMetaType::Type::Double:
1965 case QMetaType::Type::QChar:
1966 case QMetaType::Type::QString:
1967 ogrType = OFTString;
1970 case QMetaType::Type::QStringList:
1971 ogrType = OFTStringList;
1974 case QMetaType::Type::QByteArray:
1975 ogrType = OFTBinary;
1978 case QMetaType::Type::QDate:
1982 case QMetaType::Type::QTime:
1985 case QMetaType::Type::QDateTime:
1986 ogrType = OFTDateTime;
1990 ogrType = OFTString;
1997 if (
string.isEmpty() )
2005 res =
string.toInt( &ok );
2009 res =
string.toLongLong( &ok );
2013 res =
string.toDouble( &ok );
2023 res = QDate::fromString(
string, Qt::ISODate );
2028 res = QTime::fromString(
string, Qt::ISODate );
2033 res = QDateTime::fromString(
string, Qt::ISODate );
2043 return ok ? res : QVariant();
2051 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2053 int nMaxIntLen = 11;
2054 int nMaxInt64Len = 21;
2055 int nMaxDoubleLen = 20;
2056 int nMaxDoublePrec = 15;
2058 if ( driverName ==
"GPKG"_L1 )
2068 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2075 if ( driverName ==
"GPKG"_L1 )
2076 nativeTypes <<
QgsVectorDataProvider::NativeType( QObject::tr(
"JSON (string)" ), u
"JSON"_s, QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
2078 bool supportsDate =
true;
2079 bool supportsTime =
true;
2080 bool supportsDateTime =
true;
2081 bool supportsBinary =
false;
2082 bool supportIntegerList =
false;
2083 bool supportInteger64List =
false;
2084 bool supportRealList =
false;
2085 bool supportsStringList =
false;
2089 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2091 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2092 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2093 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2094 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2095 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2096 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2097 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2098 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2099 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2100 CSLDestroy( papszTokens );
2105#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2106 if ( driverName ==
"ESRI Shapefile"_L1 )
2108 supportsDateTime =
false;
2122 if ( supportsDateTime )
2127 if ( supportsBinary )
2132 if ( supportIntegerList )
2137 if ( supportInteger64List )
2142 if ( supportRealList )
2147 if ( supportsStringList )
2153 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2154 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2165#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2171 const QString name{ OGR_FldDomain_GetName( domain ) };
2172 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2174 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
2175 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
2176 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2177 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2180 std::unique_ptr< QgsFieldDomain > res;
2181 switch ( OGR_FldDomain_GetDomainType( domain ) )
2185 QList< QgsCodedValue > values;
2186 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2187 while ( codedValue && codedValue->pszCode )
2189 const QString code( codedValue->pszCode );
2194 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2200 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2207 bool minIsInclusive =
false;
2208 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2213 bool maxIsInclusive =
false;
2214 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2219 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2220 minValue, minIsInclusive,
2221 maxValue, maxIsInclusive );
2226 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2227 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2231 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2233 case OFDMP_DEFAULT_VALUE:
2239 case OFDMP_GEOMETRY_WEIGHTED:
2244 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2246 case OFDSP_DEFAULT_VALUE:
2249 case OFDSP_DUPLICATE:
2252 case OFDSP_GEOMETRY_RATIO:
2264 OGRFieldType domainFieldType = OFTInteger;
2265 OGRFieldSubType domainFieldSubType = OFSTNone;
2268 OGRFieldDomainH res =
nullptr;
2269 switch ( domain->
type() )
2273 std::vector< OGRCodedValue > enumeration;
2274 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2275 enumeration.reserve( values.size() );
2278 OGRCodedValue codedValue;
2279 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2280 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2281 enumeration.push_back( codedValue );
2284 last.pszCode =
nullptr;
2285 last.pszValue =
nullptr;
2286 enumeration.push_back( last );
2287 res = OGR_CodedFldDomain_Create(
2288 domain->
name().toUtf8().constData(),
2295 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2297 CPLFree( value.pszCode );
2298 CPLFree( value.pszValue );
2305 std::unique_ptr< OGRField > min =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2306 std::unique_ptr< OGRField > max =
variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2309 res = OGR_RangeFldDomain_Create(
2310 domain->
name().toUtf8().constData(),
2315 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2317 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2324 res = OGR_GlobFldDomain_Create(
2325 domain->
name().toUtf8().constData(),
2329 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2338 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2341 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2344 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2359 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2362 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2365 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2378#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2382 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2384 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2386 QVariantMap leftTableUriParts = datasetUriParts;
2387 leftTableUriParts.insert( u
"layerName"_s, leftTableName );
2388 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2390 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2391 QVariantMap rightTableUriParts = datasetUriParts;
2392 rightTableUriParts.insert( u
"layerName"_s, rightTableName );
2393 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2395 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2396 QString mappingTableSource;
2397 if ( !mappingTableName.isEmpty() )
2399 QVariantMap mappingTableUriParts = datasetUriParts;
2400 mappingTableUriParts.insert( u
"layerName"_s, mappingTableName );
2401 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2404 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2406 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2408 CSLDestroy( cslLeftTableFieldNames );
2410 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2412 CSLDestroy( cslRightTableFieldNames );
2414 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2416 CSLDestroy( cslLeftMappingTableFieldNames );
2418 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2420 CSLDestroy( cslRightMappingTableFieldNames );
2422 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2423 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2424 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2426 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2428 switch ( relationshipType )
2434 case GRT_ASSOCIATION:
2438 case GRT_AGGREGATION:
2439 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2443 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2445 switch ( eCardinality )
2447 case GRC_ONE_TO_ONE:
2450 case GRC_ONE_TO_MANY:
2453 case GRC_MANY_TO_ONE:
2456 case GRC_MANY_TO_MANY:
2461 switch ( cardinality )
2470 QString(), QString(), rightTableSource, u
"ogr"_s,
2471 QString(), QString(), leftTableSource, u
"ogr"_s );
2486 QString(), QString(), rightTableSource, u
"ogr"_s,
2487 QString(), QString(), leftTableSource, u
"ogr"_s );
2505 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2509 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2512 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2515 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2518 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2525 const QString leftTableName = leftParts.value( u
"layerName"_s ).toString();
2526 if ( leftTableName.isEmpty() )
2528 error = QObject::tr(
"Parent table name was not set" );
2533 const QString rightTableName = rightParts.value( u
"layerName"_s ).toString();
2534 if ( rightTableName.isEmpty() )
2536 error = QObject::tr(
"Child table name was not set" );
2540 if ( leftParts.value( u
"path"_s ).toString() != rightParts.value( u
"path"_s ).toString() )
2542 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2546 QString mappingTableName;
2550 mappingTableName = mappingParts.value( u
"layerName"_s ).toString();
2551 if ( leftParts.value( u
"path"_s ).toString() != mappingParts.value( u
"path"_s ).toString() )
2553 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2559 leftTableName.toLocal8Bit().constData(),
2560 rightTableName.toLocal8Bit().constData(),
2565 int count = leftFieldNames.count();
2566 char **lst =
nullptr;
2569 for (
const QString &
string : leftFieldNames )
2571 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2574 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2579 count = rightFieldNames.count();
2583 for (
const QString &
string : rightFieldNames )
2585 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2588 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2591 if ( !mappingTableName.isEmpty() )
2593 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2597 int count = leftFieldNames.count();
2601 for (
const QString &
string : leftFieldNames )
2603 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2606 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2611 count = rightFieldNames.count();
2615 for (
const QString &
string : rightFieldNames )
2617 lst = CSLAddString( lst,
string.toLocal8Bit().constData() );
2620 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2628 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2632 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2638 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2640 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2644 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2652 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2656 errCause = QObject::tr(
"No styles available on DB" );
2660 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2663 errCause = QObject::tr(
"No styles available on DB" );
2667 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2669 OGR_L_ResetReading( hLayer );
2671 QList<qlonglong> listTimestamp;
2672 QMap<int, QString> mapIdToStyleName;
2673 QMap<int, QString> mapIdToDescription;
2674 QMap<qlonglong, QList<int> > mapTimestampToId;
2675 int numberOfRelatedStyles = 0;
2683 QString tableName( QString::fromUtf8(
2684 OGR_F_GetFieldAsString( hFeature.get(),
2685 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2686 QString geometryColumn( QString::fromUtf8(
2687 OGR_F_GetFieldAsString( hFeature.get(),
2688 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2689 QString styleName( QString::fromUtf8(
2690 OGR_F_GetFieldAsString( hFeature.get(),
2691 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2692 QString description( QString::fromUtf8(
2693 OGR_F_GetFieldAsString( hFeature.get(),
2694 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2695 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2696 if ( tableName == layerName &&
2697 geometryColumn == geomColumn )
2700 QString id( QString::number( fid ) );
2702 names.append( styleName );
2703 descriptions.append( description );
2704 ++ numberOfRelatedStyles;
2708 int year, month, day, hour, minute, second, TZ;
2709 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2710 &year, &month, &day, &hour, &minute, &second, &TZ );
2711 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2712 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2714 listTimestamp.append( ts );
2715 mapIdToStyleName[fid] = styleName;
2716 mapIdToDescription[fid] = description;
2717 mapTimestampToId[ts].append( fid );
2721 std::sort( listTimestamp.begin(), listTimestamp.end() );
2723 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2725 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2726 for (
int j = 0; j < listId.size(); j++ )
2728 int fid = listId[j];
2729 QString id( QString::number( fid ) );
2731 names.append( mapIdToStyleName[fid] );
2732 descriptions.append( mapIdToDescription[fid] );
2736 return numberOfRelatedStyles;
2744 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2748 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2750 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2751 " AND f_table_name=%1"
2752 " AND f_geometry_column=%2"
2753 " AND styleName=%3" )
2754 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2755 QgsOgrProviderUtils::quotedValue( geomColumn ),
2756 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2757 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2758 OGR_L_ResetReading( hLayer );
2760 OGR_L_ResetReading( hLayer );
2770 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2774 errCause = QObject::tr(
"No styles available on DB" );
2779 int id = styleId.toInt( &ok );
2782 errCause = QObject::tr(
"Invalid style identifier" );
2789 errCause = QObject::tr(
"No style corresponding to style identifier" );
2793 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2794 QString styleQML( QString::fromUtf8(
2795 OGR_F_GetFieldAsString( hFeature.get(),
2796 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2797 OGR_L_ResetReading( hLayer );
2806 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2811 errCause = QObject::tr(
"Connection to database failed" );
2816 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2818 errCause = QObject::tr(
"Error executing the delete query." );
2831 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2835 errCause = QObject::tr(
"No styles available on DB" );
2839 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2840 " AND f_table_name=%1"
2841 " AND f_geometry_column=%2"
2842 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2843 ",update_time DESC" )
2844 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2845 QgsOgrProviderUtils::quotedValue( geomColumn ) );
2846 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2847 OGR_L_ResetReading( hLayer );
2848 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2850 qlonglong moreRecentTimestamp = 0;
2856 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2858 styleQML = QString::fromUtf8(
2859 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2860 styleName = QString::fromUtf8(
2861 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2865 int year, month, day, hour, minute, second, TZ;
2866 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2867 &year, &month, &day, &hour, &minute, &second, &TZ );
2868 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2869 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2870 if ( ts > moreRecentTimestamp )
2872 moreRecentTimestamp = ts;
2873 styleQML = QString::fromUtf8(
2874 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2875 styleName = QString::fromUtf8(
2876 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2879 OGR_L_ResetReading( hLayer );
2885 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
2886 const QString &styleName,
const QString &styleDescription,
2887 const QString &uiFileContent,
bool useAsDefault, QString &errCause
2891 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2898 char **options =
nullptr;
2900 options = CSLSetNameValue( options,
"FID",
"id" );
2901 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
2902 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
2903 CSLDestroy( options );
2906 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2912 OGR_Fld_SetWidth( fld.get(), 256 );
2913 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2917 OGR_Fld_SetWidth( fld.get(), 256 );
2918 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2922 OGR_Fld_SetWidth( fld.get(), 256 );
2923 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2927 OGR_Fld_SetWidth( fld.get(), 256 );
2928 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2932 OGR_Fld_SetWidth( fld.get(), 30 );
2933 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2937 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2941 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2945 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
2946 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2950 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2954 OGR_Fld_SetWidth( fld.get(), 30 );
2955 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2959 OGR_Fld_SetWidth( fld.get(), 30 );
2960 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2964 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
2965 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2969 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2974 QString realStyleName =
2975 styleName.isEmpty() ? layerName : styleName;
2977 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2981 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
2982 " AND f_table_name=%1"
2983 " AND f_geometry_column=%2" )
2984 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
2985 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
2986 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
2990 OGR_F_SetFieldInteger( hFeature.get(),
2991 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
2993 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
2996 QgsDebugError( u
"Could not unset previous useAsDefault style"_s );
3001 QString checkQuery = QStringLiteral(
"f_table_schema=''"
3002 " AND f_table_name=%1"
3003 " AND f_geometry_column=%2"
3004 " AND styleName=%3" )
3005 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3006 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
3007 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
3008 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
3009 OGR_L_ResetReading( hLayer );
3011 OGR_L_ResetReading( hLayer );
3020 hFeature.reset( OGR_F_Create( hLayerDefn ) );
3021 OGR_F_SetFieldString( hFeature.get(),
3022 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
3024 OGR_F_SetFieldString( hFeature.get(),
3025 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
3027 OGR_F_SetFieldString( hFeature.get(),
3028 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
3029 layerName.toUtf8().constData() );
3030 OGR_F_SetFieldString( hFeature.get(),
3031 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
3032 geomColumn.toUtf8().constData() );
3033 OGR_F_SetFieldString( hFeature.get(),
3034 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
3035 realStyleName.toUtf8().constData() );
3036 if ( !uiFileContent.isEmpty() )
3038 OGR_F_SetFieldString( hFeature.get(),
3039 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
3040 uiFileContent.toUtf8().constData() );
3043 OGR_F_SetFieldString( hFeature.get(),
3044 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3045 qmlStyle.toUtf8().constData() );
3046 OGR_F_SetFieldString( hFeature.get(),
3047 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3048 sldStyle.toUtf8().constData() );
3049 OGR_F_SetFieldInteger( hFeature.get(),
3050 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3051 useAsDefault ? 1 : 0 );
3052 OGR_F_SetFieldString( hFeature.get(),
3053 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3054 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3055 OGR_F_SetFieldString( hFeature.get(),
3056 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3061 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3063 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3068 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 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 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.