40#include "qgsogrproviderutils.h"
42#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
53#include <QJsonDocument>
58#include <QRegularExpression>
60#include "ogr_srs_api.h"
65 OGR_DS_Destroy( source );
71 OGR_G_DestroyGeometry( geometry );
76 OGR_Fld_Destroy( definition );
81 OGR_F_Destroy( feature );
98 CPLPushErrorHandler( CPLQuietErrorHandler );
99 GDALDeleteDataset( driver, path.toUtf8().constData() );
100 CPLPopErrorHandler();
111 GDALDestroyWarpOptions( options );
114#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
117 GDALDestroyRelationship( relationship );
121static void setQTTimeZoneFromOGRTZFlag( QDateTime &dt,
int nTZFlag )
128 else if ( nTZFlag == 1 )
130 dt.setTimeSpec( Qt::LocalTime );
132 else if ( nTZFlag == 100 )
134 dt.setTimeSpec( Qt::UTC );
140 dt.setOffsetFromUtc( ( nTZFlag - 100 ) * 15 * 60 );
146 if ( !value || OGR_RawField_IsUnset( value ) || OGR_RawField_IsNull( value ) )
152 return value->Integer;
155 return value->Integer64;
162 return QString::fromUtf8( value->String );
165 return QDate( value->Date.Year, value->Date.Month, value->Date.Day );
169 float secondsPart = 0;
170 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
171 return QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
176 float secondsPart = 0;
177 float millisecondPart = std::modf( value->Date.Second, &secondsPart );
178 QDateTime dt = QDateTime( QDate( value->Date.Year, value->Date.Month, value->Date.Day ),
179 QTime( value->Date.Hour, value->Date.Minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
180 setQTTimeZoneFromOGRTZFlag( dt, value->Date.TZFlag );
186 Q_ASSERT_X(
false,
"QgsOgrUtils::OGRFieldtoVariant",
"OFTBinary type not supported" );
192 res.reserve( value->IntegerList.nCount );
193 for (
int i = 0; i < value->IntegerList.nCount; ++i )
194 res << value->IntegerList.paList[ i ];
198 case OFTInteger64List:
201 res.reserve( value->Integer64List.nCount );
202 for (
int i = 0; i < value->Integer64List.nCount; ++i )
203 res << value->Integer64List.paList[ i ];
210 res.reserve( value->RealList.nCount );
211 for (
int i = 0; i < value->RealList.nCount; ++i )
212 res << value->RealList.paList[ i ];
217 case OFTWideStringList:
220 res.reserve( value->StringList.nCount );
221 for (
int i = 0; i < value->StringList.nCount; ++i )
222 res << QString::fromUtf8( value->StringList.paList[ i ] );
231 if ( datetime.timeSpec() == Qt::LocalTime )
233 return 100 + datetime.offsetFromUtc() / ( 60 * 15 );
238 std::unique_ptr< OGRField > res = std::make_unique< OGRField >();
240 switch ( value.userType() )
242 case QMetaType::Type::UnknownType:
243 OGR_RawField_SetUnset( res.get() );
245 case QMetaType::Type::Bool:
247 const int val = value.toBool() ? 1 : 0;
248 if ( type == OFTInteger )
250 else if ( type == OFTInteger64 )
251 res->Integer64 = val;
252 else if ( type == OFTReal )
261 case QMetaType::Type::Int:
263 const int val = value.toInt();
264 if ( type == OFTInteger )
266 else if ( type == OFTInteger64 )
267 res->Integer64 = val;
268 else if ( type == OFTReal )
277 case QMetaType::Type::LongLong:
279 const qint64 val = value.toLongLong();
280 if ( type == OFTInteger )
282 if ( val <= std::numeric_limits<int>::max() &&
283 val >= std::numeric_limits<int>::min() )
285 res->Integer =
static_cast<int>( val );
293 else if ( type == OFTInteger64 )
294 res->Integer64 = val;
295 else if ( type == OFTReal )
297 res->Real =
static_cast<double>( val );
301 QgsDebugError(
"Unsupported output data type for LongLong" );
306 case QMetaType::Type::Double:
308 double val = value.toDouble();
309 if ( type == OFTInteger )
311 if ( val <= std::numeric_limits<int>::max() &&
312 val >= std::numeric_limits<int>::min() )
314 res->Integer =
static_cast<int>( val );
322 else if ( type == OFTInteger64 )
324 if ( val <=
static_cast<double>( std::numeric_limits<qint64>::max() ) &&
325 val >=
static_cast<double>( std::numeric_limits<qint64>::min() ) )
327 res->Integer64 =
static_cast<qint64
>( val );
335 else if ( type == OFTReal )
341 QgsDebugError(
"Unsupported output data type for LongLong" );
346 case QMetaType::Type::QChar:
347 case QMetaType::Type::QString:
349 if ( type == OFTString )
350 res->String = CPLStrdup( value.toString().toUtf8().constData() );
358 case QMetaType::Type::QDate:
360 if ( type == OFTDate )
362 const QDate date = value.toDate();
363 res->Date.Day = date.day();
364 res->Date.Month = date.month();
365 res->Date.Year =
static_cast<GInt16
>( date.year() );
366 res->Date.TZFlag = 0;
375 case QMetaType::Type::QTime:
377 if ( type == OFTTime )
379 const QTime time = value.toTime();
380 res->Date.Hour = time.hour();
381 res->Date.Minute = time.minute();
382 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
383 res->Date.TZFlag = 0;
392 case QMetaType::Type::QDateTime:
394 if ( type == OFTDateTime )
396 const QDateTime dt = value.toDateTime();
397 const QDate date = dt.date();
398 res->Date.Day = date.day();
399 res->Date.Month = date.month();
400 res->Date.Year =
static_cast<GInt16
>( date.year() );
401 const QTime time = dt.time();
402 res->Date.Hour = time.hour();
403 res->Date.Minute = time.minute();
404 res->Date.Second =
static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 );
405 res->Date.TZFlag = OGRTZFlagFromQt( dt );
409 QgsDebugError(
"Unsupported output data type for DateTime" );
416 QgsDebugError(
"Unhandled variant type in variantToOGRField" );
417 OGR_RawField_SetUnset( res.get() );
433 feature.
setId( OGR_F_GetFID( ogrFet ) );
436 if ( !readOgrFeatureGeometry( ogrFet, feature ) )
441 if ( !readOgrFeatureAttributes( ogrFet, fields, feature, encoding ) )
456 int fieldCount = OGR_F_GetFieldCount( ogrFet );
457 for (
int i = 0; i < fieldCount; ++i )
459 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, i );
466 QString name = encoding ? encoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ) : QString::fromUtf8( OGR_Fld_GetNameRef( fldDef ) );
467 QMetaType::Type varType;
468 switch ( OGR_Fld_GetType( fldDef ) )
471 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
472 varType = QMetaType::Type::Bool;
474 varType = QMetaType::Type::Int;
477 varType = QMetaType::Type::LongLong;
480 varType = QMetaType::Type::Double;
483 varType = QMetaType::Type::QDate;
486 varType = QMetaType::Type::QTime;
489 varType = QMetaType::Type::QDateTime;
492 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
493 varType = QMetaType::Type::QVariantMap;
495 varType = QMetaType::Type::QString;
498 varType = QMetaType::Type::QString;
508 if ( attIndex < 0 || attIndex >= fields.
count() )
516 return getOgrFeatureAttribute( ogrFet, field, attIndex, encoding, ok );
521 if ( !ogrFet || attIndex < 0 )
528 OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attIndex );
535 QgsDebugError( QStringLiteral(
"ogrFet->GetFieldDefnRef(attindex) returns NULL" ) );
544 if ( OGR_F_IsFieldSetAndNotNull( ogrFet, attIndex ) )
546 switch ( field.
type() )
548 case QMetaType::Type::QString:
551 value = QVariant( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
553 value = QVariant( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ) );
558 if ( value.isNull() )
559 value = QVariant( QStringLiteral(
"" ) );
564 case QMetaType::Type::Int:
565 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
567 case QMetaType::Type::Bool:
568 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
570 case QMetaType::Type::LongLong:
571 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
573 case QMetaType::Type::Double:
574 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
576 case QMetaType::Type::QDate:
577 case QMetaType::Type::QDateTime:
578 case QMetaType::Type::QTime:
580 int year, month, day, hour, minute, tzf;
582 float secondsPart = 0;
584 OGR_F_GetFieldAsDateTimeEx( ogrFet, attIndex, &year, &month, &day, &hour, &minute, &second, &tzf );
585 float millisecondPart = std::modf( second, &secondsPart );
587 if ( field.
type() == QMetaType::Type::QDate )
588 value = QDate( year, month, day );
589 else if ( field.
type() == QMetaType::Type::QTime )
590 value = QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) );
593 QDateTime dt = QDateTime( QDate( year, month, day ),
594 QTime( hour, minute,
static_cast< int >( secondsPart ),
static_cast< int >( std::round( 1000 * millisecondPart ) ) ) );
595 setQTTimeZoneFromOGRTZFlag( dt, tzf );
601 case QMetaType::Type::QByteArray:
604 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
608 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
615 case QMetaType::Type::QStringList:
618 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
619 const int count = CSLCount( lst );
622 list.reserve( count );
623 for (
int i = 0; i < count; i++ )
626 list << encoding->toUnicode( lst[i] );
628 list << QString::fromUtf8( lst[i] );
635 case QMetaType::Type::QVariantList:
639 case QMetaType::Type::QString:
642 char **lst = OGR_F_GetFieldAsStringList( ogrFet, attIndex );
643 const int count = CSLCount( lst );
646 list.reserve( count );
647 for (
int i = 0; i < count; i++ )
650 list << encoding->toUnicode( lst[i] );
652 list << QString::fromUtf8( lst[i] );
659 case QMetaType::Type::Int:
663 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
666 list.reserve( count );
667 for (
int i = 0; i < count; i++ )
676 case QMetaType::Type::Double:
680 const double *lst = OGR_F_GetFieldAsDoubleList( ogrFet, attIndex, &count );
683 list.reserve( count );
684 for (
int i = 0; i < count; i++ )
693 case QMetaType::Type::LongLong:
697 const long long *lst = OGR_F_GetFieldAsInteger64List( ogrFet, attIndex, &count );
700 list.reserve( count );
701 for (
int i = 0; i < count; i++ )
712 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
721 case QMetaType::Type::QVariantMap:
726 value = QJsonDocument::fromJson( encoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
728 value = QJsonDocument::fromJson( QString::fromUtf8( OGR_F_GetFieldAsString( ogrFet, attIndex ) ).toUtf8() ).toVariant();
732 Q_ASSERT_X(
false,
"QgsOgrUtils::getOgrFeatureAttribute",
"unsupported field type" );
755 for (
int idx = 0; idx < fields.
count(); ++idx )
757 QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok );
771 OGRGeometryH geom = OGR_F_GetGeometryRef( ogrFet );
775 feature.
setGeometry( ogrGeometryToQgsGeometry( geom ) );
785 OGR_G_GetPointZM( geom, 0, &x, &y, &z, &m );
786 return std::make_unique< QgsPoint >( wkbType, x, y, z, m );
791 std::unique_ptr< QgsMultiPoint > mp = std::make_unique< QgsMultiPoint >();
793 const int count = OGR_G_GetGeometryCount( geom );
794 mp->reserve( count );
795 for (
int i = 0; i < count; ++i )
807 int count = OGR_G_GetPointCount( geom );
808 QVector< double > x( count );
809 QVector< double > y( count );
811 double *pz =
nullptr;
817 double *pm =
nullptr;
824 OGR_G_GetPointsZM( geom, x.data(),
sizeof(
double ), y.data(),
sizeof(
double ), pz,
sizeof(
double ), pm,
sizeof(
double ) );
831 std::unique_ptr< QgsMultiLineString > mp = std::make_unique< QgsMultiLineString >();
833 const int count = OGR_G_GetGeometryCount( geom );
834 mp->reserve( count );
835 for (
int i = 0; i < count; ++i )
845 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
847 const int count = OGR_G_GetGeometryCount( geom );
853 for (
int i = 1; i < count; ++i )
863 std::unique_ptr< QgsMultiPolygon > polygon = std::make_unique< QgsMultiPolygon >();
865 const int count = OGR_G_GetGeometryCount( geom );
866 polygon->reserve( count );
867 for (
int i = 0; i < count; ++i )
877 switch ( ogrGeomType )
966 const auto ogrGeomType = OGR_G_GetGeometryType( geom );
967 Qgis::WkbType wkbType = ogrGeometryTypeToQgsWkbType( ogrGeomType );
1009 if ( wkbFlatten( wkbType ) == wkbGeometryCollection )
1012 if ( OGR_G_GetGeometryCount( geom ) >= 1 &&
1013 wkbFlatten( OGR_G_GetGeometryType( OGR_G_GetGeometryRef( geom, 0 ) ) ) == wkbTIN )
1015 auto newGeom = OGR_G_ForceToMultiPolygon( OGR_G_Clone( geom ) );
1016 auto ret = ogrGeometryToQgsGeometry( newGeom );
1017 OGR_G_DestroyGeometry( newGeom );
1023 int memorySize = OGR_G_WkbSize( geom );
1024 unsigned char *wkb =
new unsigned char[memorySize];
1028 uint32_t origGeomType;
1029 memcpy( &origGeomType, wkb + 1,
sizeof( uint32_t ) );
1030 bool hasZ = ( origGeomType >= 1000 && origGeomType < 2000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
1031 bool hasM = ( origGeomType >= 2000 && origGeomType < 3000 ) || ( origGeomType >= 3000 && origGeomType < 4000 );
1034 if ( origGeomType % 1000 == 16 )
1037 int nDims = 2 + hasZ + hasM;
1040 unsigned char *wkbptr = wkb;
1046 memcpy( wkbptr, &newMultiType,
sizeof( uint32_t ) );
1051 memcpy( &numGeoms, wkb + 5,
sizeof( uint32_t ) );
1055 for ( uint32_t i = 0; i < numGeoms; ++i )
1061 memcpy( wkbptr, &newSingleType,
sizeof( uint32_t ) );
1062 wkbptr +=
sizeof( uint32_t );
1066 memcpy( &nRings, wkbptr,
sizeof( uint32_t ) );
1067 wkbptr +=
sizeof( uint32_t );
1069 for ( uint32_t j = 0; j < nRings; ++j )
1072 memcpy( &nPoints, wkbptr,
sizeof( uint32_t ) );
1073 wkbptr +=
sizeof( uint32_t ) +
sizeof(
double ) * nDims * nPoints;
1077 else if ( origGeomType % 1000 == 15 )
1082 memcpy( wkb + 1, &newType,
sizeof( uint32_t ) );
1093 if (
string.isEmpty() )
1096 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1099 QByteArray ba =
string.toUtf8();
1100 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1101 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1106 VSIUnlink( randomFileName.toUtf8().constData() );
1110 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1114 VSIUnlink( randomFileName.toUtf8().constData() );
1119 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1121 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
1127 VSIUnlink( randomFileName.toUtf8().constData() );
1135 if (
string.isEmpty() )
1138 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1141 QByteArray ba =
string.toUtf8();
1142 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1143 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1148 VSIUnlink( randomFileName.toUtf8().constData() );
1152 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1156 VSIUnlink( randomFileName.toUtf8().constData() );
1162 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1164 fields = readOgrFields( oFeat.get(), encoding );
1168 VSIUnlink( randomFileName.toUtf8().constData() );
1177 QStringList strings;
1179 for (
qgssize i = 0; stringList[i]; ++i )
1181 strings.
append( QString::fromUtf8( stringList[i] ) );
1192 char *pszWkt =
nullptr;
1193 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=NO" ).toLocal8Bit();
1194 const QByteArray formatOption = QStringLiteral(
"FORMAT=WKT2" ).toLocal8Bit();
1195 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1196 OSRExportToWktEx( srs, &pszWkt, options );
1198 const QString res( pszWkt );
1205 const QString wkt = OGRSpatialReferenceToWkt( srs );
1206 if ( wkt.isEmpty() )
1209 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1210 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1212 if ( authorityName && authorityCode )
1214 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1217 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1218 OSRIsSame( srs, ogrSrsTmp ) )
1223 OSRDestroySpatialReference( ogrSrsTmp );
1228#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1229 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1230 if ( coordinateEpoch > 0 )
1248 if ( !authId.isEmpty() )
1250 ogrSrs = OSRNewSpatialReference(
nullptr );
1251 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1255 if ( ogrSrsFromWkt )
1257 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1259 OSRDestroySpatialReference( ogrSrs );
1260 ogrSrs = ogrSrsFromWkt;
1264 OSRDestroySpatialReference( ogrSrsFromWkt );
1270 OSRDestroySpatialReference( ogrSrs );
1276 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1280 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1281#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1296 const QString cpgEncoding = readShapefileEncodingFromCpg( path );
1297 if ( !cpgEncoding.isEmpty() )
1300 return readShapefileEncodingFromLdid( path );
1306 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1307 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_CPG" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1313 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1314 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_LDID" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1321 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1323 | CSLT_PRESERVEQUOTES
1324 | CSLT_PRESERVEESCAPES );
1325 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1331 const thread_local QRegularExpression sToolPartRx( QStringLiteral(
"^(.*?)\\((.*)\\)$" ) );
1332 const QString stylePart( papszStyleString[i] );
1333 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1334 if ( !match.hasMatch() )
1337 const QString tool = match.captured( 1 );
1338 const QString params = match.captured( 2 );
1340 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1341 | CSLT_PRESERVEESCAPES );
1343 QVariantMap toolParts;
1344 const thread_local QRegularExpression sToolParamRx( QStringLiteral(
"^(.*?):(.*)$" ) );
1345 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1347 const QString toolPart( papszTokens[j] );
1348 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1349 if ( !match.hasMatch() )
1353 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1355 CSLDestroy( papszTokens );
1358 styles.insert( tool.toLower(), toolParts );
1360 CSLDestroy( papszStyleString );
1366 const QVariantMap styles = parseStyleString(
string );
1368 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1370 const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
1371 const QRegularExpressionMatch match = sUnitRx.match( size );
1372 if ( match.hasMatch() )
1374 value = match.captured( 1 ).toDouble();
1375 const QString unitString = match.captured( 2 );
1376 if ( unitString.compare( QLatin1String(
"px" ), Qt::CaseInsensitive ) == 0 )
1380 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1381 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1383 value *= PX_TO_PT_FACTOR;
1386 else if ( unitString.compare( QLatin1String(
"pt" ), Qt::CaseInsensitive ) == 0 )
1391 else if ( unitString.compare( QLatin1String(
"mm" ), Qt::CaseInsensitive ) == 0 )
1396 else if ( unitString.compare( QLatin1String(
"cm" ), Qt::CaseInsensitive ) == 0 )
1402 else if ( unitString.compare( QLatin1String(
"in" ), Qt::CaseInsensitive ) == 0 )
1407 else if ( unitString.compare( QLatin1String(
"g" ), Qt::CaseInsensitive ) == 0 )
1412 QgsDebugError( QStringLiteral(
"Unknown unit %1" ).arg( unitString ) );
1416 QgsDebugError( QStringLiteral(
"Could not parse style size %1" ).arg( size ) );
1421 auto convertColor = [](
const QString & string ) -> QColor
1423 if (
string.isEmpty() )
1426 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral(
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
1427 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1428 if ( match.hasMatch() )
1431 return QColor( QStringLiteral(
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
1435 return QColor(
string );
1439 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1441 QColor color = convertColor( lineStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1445 convertSize( lineStyle.value( QStringLiteral(
"w" ) ).toString(), lineWidth, lineWidthUnit );
1448 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-pen-(\\d+)" ) );
1449 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1450 if ( match.hasMatch() )
1452 const int penId = match.captured( 1 ).toInt();
1459 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1460 simpleLine->setWidthUnit( lineWidthUnit );
1463 const QString pattern = lineStyle.value( QStringLiteral(
"p" ) ).toString();
1464 if ( !pattern.isEmpty() )
1466 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
1467 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1468 if ( match.hasMatch() )
1470 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1471 QVector< qreal > dashPattern;
1473 for (
const QString &val : patternValues )
1476 convertSize( val + match.captured( 2 ), length, patternUnits );
1477 dashPattern.push_back( length * lineWidth * 2 );
1480 simpleLine->setCustomDashVector( dashPattern );
1481 simpleLine->setCustomDashPatternUnit( patternUnits );
1482 simpleLine->setUseCustomDashPattern(
true );
1486 Qt::PenCapStyle capStyle = Qt::FlatCap;
1487 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1489 const QString
id = lineStyle.value( QStringLiteral(
"id" ) ).toString();
1490 if (
id.contains( QLatin1String(
"mapinfo-pen" ), Qt::CaseInsensitive ) )
1495 capStyle = Qt::RoundCap;
1496 joinStyle = Qt::RoundJoin;
1500 const QString penCap = lineStyle.value( QStringLiteral(
"cap" ) ).toString();
1501 if ( penCap.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1503 capStyle = Qt::FlatCap;
1505 else if ( penCap.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1507 capStyle = Qt::RoundCap;
1509 else if ( penCap.compare( QLatin1String(
"p" ), Qt::CaseInsensitive ) == 0 )
1511 capStyle = Qt::SquareCap;
1513 simpleLine->setPenCapStyle( capStyle );
1516 const QString penJoin = lineStyle.value( QStringLiteral(
"j" ) ).toString();
1517 if ( penJoin.compare( QLatin1String(
"m" ), Qt::CaseInsensitive ) == 0 )
1519 joinStyle = Qt::MiterJoin;
1521 else if ( penJoin.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1523 joinStyle = Qt::RoundJoin;
1525 else if ( penJoin.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1527 joinStyle = Qt::BevelJoin;
1529 simpleLine->setPenJoinStyle( joinStyle );
1531 const QString priority = lineStyle.value( QStringLiteral(
"l" ) ).toString();
1532 if ( !priority.isEmpty() )
1534 simpleLine->setRenderingPass( priority.toInt() );
1536 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1539 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1541 const QColor foreColor = convertColor( brushStyle.value( QStringLiteral(
"fc" ), QStringLiteral(
"#000000" ) ).toString() );
1542 const QColor backColor = convertColor( brushStyle.value( QStringLiteral(
"bc" ), QString() ).toString() );
1544 const QString
id = brushStyle.value( QStringLiteral(
"id" ) ).toString();
1547 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-brush-(\\d+)" ) );
1548 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1549 if ( match.hasMatch() )
1551 const int brushId = match.captured( 1 ).toInt();
1558 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-brush-(\\d+)" ) );
1559 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1561 Qt::BrushStyle style = Qt::SolidPattern;
1562 if ( ogrMatch.hasMatch() )
1564 const int brushId = ogrMatch.captured( 1 ).toInt();
1568 style = Qt::SolidPattern;
1572 style = Qt::NoBrush;
1576 style = Qt::HorPattern;
1580 style = Qt::VerPattern;
1584 style = Qt::FDiagPattern;
1588 style = Qt::BDiagPattern;
1592 style = Qt::CrossPattern;
1596 style = Qt::DiagCrossPattern;
1602 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1604 std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1605 backgroundFill->setLocked(
true );
1606 backgroundFill->setStrokeStyle( Qt::NoPen );
1607 layers << backgroundFill.release();
1610 std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1611 foregroundFill->setBrushStyle( style );
1612 foregroundFill->setStrokeStyle( Qt::NoPen );
1614 const QString priority = brushStyle.value( QStringLiteral(
"l" ) ).toString();
1615 if ( !priority.isEmpty() )
1617 foregroundFill->setRenderingPass( priority.toInt() );
1619 layers << foregroundFill.release();
1620 return std::make_unique< QgsFillSymbol >( layers );
1623 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1625 const QColor color = convertColor( symbolStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1629 convertSize( symbolStyle.value( QStringLiteral(
"s" ) ).toString(), symbolSize, symbolSizeUnit );
1631 const double angle = symbolStyle.value( QStringLiteral(
"a" ), QStringLiteral(
"0" ) ).toDouble();
1633 const QString
id = symbolStyle.value( QStringLiteral(
"id" ) ).toString();
1636 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-sym-(\\d+)" ) );
1637 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1638 if ( match.hasMatch() )
1640 const int symbolId = match.captured( 1 ).toInt();
1651 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1653 const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral(
"font-sym-(\\d+)" ) );
1654 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1655 if ( fontMatch.hasMatch() )
1657 const int symId = fontMatch.captured( 1 ).toInt();
1658 const QStringList families = symbolStyle.value( QStringLiteral(
"f" ), QString() ).toString().split(
',' );
1660 bool familyFound =
false;
1663 for (
const QString &family : std::as_const( families ) )
1671 fontFamily = processedFamily;
1678 std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1679 fontMarker->setSizeUnit( symbolSizeUnit );
1680 fontMarker->setAngle( -angle );
1682 fontMarker->setColor( color );
1684 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1685 if ( strokeColor.isValid() )
1687 fontMarker->setStrokeColor( strokeColor );
1688 fontMarker->setStrokeWidth( 1 );
1693 fontMarker->setStrokeWidth( 0 );
1696 markerLayer = std::move( fontMarker );
1698 else if ( !families.empty() )
1707 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-sym-(\\d+)" ) );
1708 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1711 bool isFilled =
true;
1712 if ( ogrMatch.hasMatch() )
1714 const int symId = ogrMatch.captured( 1 ).toInt();
1777 std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
1778 simpleMarker->setSizeUnit( symbolSizeUnit );
1779 simpleMarker->setStrokeWidth( 1.0 );
1784 simpleMarker->setColor( color );
1785 simpleMarker->setStrokeStyle( Qt::NoPen );
1789 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1790 simpleMarker->setStrokeColor( color );
1793 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1794 if ( strokeColor.isValid() )
1796 simpleMarker->setStrokeColor( strokeColor );
1797 simpleMarker->setStrokeStyle( Qt::SolidLine );
1800 markerLayer = std::move( simpleMarker );
1803 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1809 if ( styles.contains( QStringLiteral(
"symbol" ) ) )
1811 const QVariantMap symbolStyle = styles.value( QStringLiteral(
"symbol" ) ).toMap();
1812 return convertSymbol( symbolStyle );
1820 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1823 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1824 return convertPen( lineStyle );
1833 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1834 if ( styles.contains( QStringLiteral(
"brush" ) ) )
1836 const QVariantMap brushStyle = styles.value( QStringLiteral(
"brush" ) ).toMap();
1837 fillSymbol = convertBrush( brushStyle );
1841 std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1842 emptyFill->setBrushStyle( Qt::NoBrush );
1843 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1846 std::unique_ptr< QgsSymbol > penSymbol;
1847 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1849 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1850 penSymbol = convertPen( lineStyle );
1855 const int count = penSymbol->symbolLayerCount();
1865 for (
int i = 0; i < count; ++i )
1867 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1868 layer->setLocked(
true );
1869 fillSymbol->appendSymbolLayer( layer.release() );
1885 variantType = QMetaType::Type::UnknownType;
1886 variantSubType = QMetaType::Type::UnknownType;
1891 if ( ogrSubType == OFSTBoolean )
1893 variantType = QMetaType::Type::Bool;
1894 ogrSubType = OFSTBoolean;
1897 variantType = QMetaType::Type::Int;
1900 variantType = QMetaType::Type::LongLong;
1903 variantType = QMetaType::Type::Double;
1906 variantType = QMetaType::Type::QDate;
1909 variantType = QMetaType::Type::QTime;
1912 variantType = QMetaType::Type::QDateTime;
1916 variantType = QMetaType::Type::QByteArray;
1921 if ( ogrSubType == OFSTJSON )
1923 ogrSubType = OFSTJSON;
1924 variantType = QMetaType::Type::QVariantMap;
1925 variantSubType = QMetaType::Type::QString;
1929 variantType = QMetaType::Type::QString;
1934 case OFTWideStringList:
1935 variantType = QMetaType::Type::QStringList;
1936 variantSubType = QMetaType::Type::QString;
1939 case OFTIntegerList:
1940 variantType = QMetaType::Type::QVariantList;
1941 variantSubType = QMetaType::Type::Int;
1945 variantType = QMetaType::Type::QVariantList;
1946 variantSubType = QMetaType::Type::Double;
1949 case OFTInteger64List:
1950 variantType = QMetaType::Type::QVariantList;
1951 variantSubType = QMetaType::Type::LongLong;
1958 ogrSubType = OFSTNone;
1959 switch ( variantType )
1961 case QMetaType::Type::Bool:
1962 ogrType = OFTInteger;
1963 ogrSubType = OFSTBoolean;
1966 case QMetaType::Type::Int:
1967 ogrType = OFTInteger;
1970 case QMetaType::Type::LongLong:
1971 ogrType = OFTInteger64;
1974 case QMetaType::Type::Double:
1978 case QMetaType::Type::QChar:
1979 case QMetaType::Type::QString:
1980 ogrType = OFTString;
1983 case QMetaType::Type::QStringList:
1984 ogrType = OFTStringList;
1987 case QMetaType::Type::QByteArray:
1988 ogrType = OFTBinary;
1991 case QMetaType::Type::QDate:
1995 case QMetaType::Type::QTime:
1998 case QMetaType::Type::QDateTime:
1999 ogrType = OFTDateTime;
2003 ogrType = OFTString;
2010 if (
string.isEmpty() )
2018 res =
string.toInt( &ok );
2022 res =
string.toLongLong( &ok );
2026 res =
string.toDouble( &ok );
2036 res = QDate::fromString(
string, Qt::ISODate );
2041 res = QTime::fromString(
string, Qt::ISODate );
2046 res = QDateTime::fromString(
string, Qt::ISODate );
2056 return ok ? res : QVariant();
2064 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2066 int nMaxIntLen = 11;
2067 int nMaxInt64Len = 21;
2068 int nMaxDoubleLen = 20;
2069 int nMaxDoublePrec = 15;
2071 if ( driverName == QLatin1String(
"GPKG" ) )
2081 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2085 <<
QgsVectorDataProvider::NativeType( QObject::tr(
"Decimal number (real)" ), QStringLiteral(
"double" ), QMetaType::Type::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
2088 if ( driverName == QLatin1String(
"GPKG" ) )
2089 nativeTypes <<
QgsVectorDataProvider::NativeType( QObject::tr(
"JSON (string)" ), QStringLiteral(
"JSON" ), QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
2091 bool supportsDate =
true;
2092 bool supportsTime =
true;
2093 bool supportsDateTime =
true;
2094 bool supportsBinary =
false;
2095 bool supportIntegerList =
false;
2096 bool supportInteger64List =
false;
2097 bool supportRealList =
false;
2098 bool supportsStringList =
false;
2102 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2104 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2105 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2106 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2107 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2108 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2109 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2110 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2111 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2112 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2113 CSLDestroy( papszTokens );
2118#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2119 if ( driverName == QLatin1String(
"ESRI Shapefile" ) )
2121 supportsDateTime =
false;
2135 if ( supportsDateTime )
2140 if ( supportsBinary )
2145 if ( supportIntegerList )
2150 if ( supportInteger64List )
2155 if ( supportRealList )
2160 if ( supportsStringList )
2166 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2167 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2178#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2184 const QString name{ OGR_FldDomain_GetName( domain ) };
2185 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2187 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
2188 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
2189 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2190 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2191 ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
2193 std::unique_ptr< QgsFieldDomain > res;
2194 switch ( OGR_FldDomain_GetDomainType( domain ) )
2198 QList< QgsCodedValue > values;
2199 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2200 while ( codedValue && codedValue->pszCode )
2202 const QString code( codedValue->pszCode );
2207 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2208 values.append(
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
2213 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2220 bool minIsInclusive =
false;
2221 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2226 bool maxIsInclusive =
false;
2227 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2232 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2233 minValue, minIsInclusive,
2234 maxValue, maxIsInclusive );
2239 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2240 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2244 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2246 case OFDMP_DEFAULT_VALUE:
2252 case OFDMP_GEOMETRY_WEIGHTED:
2257 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2259 case OFDSP_DEFAULT_VALUE:
2262 case OFDSP_DUPLICATE:
2265 case OFDSP_GEOMETRY_RATIO:
2277 OGRFieldType domainFieldType = OFTInteger;
2278 OGRFieldSubType domainFieldSubType = OFSTNone;
2279 variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
2281 OGRFieldDomainH res =
nullptr;
2282 switch ( domain->
type() )
2286 std::vector< OGRCodedValue > enumeration;
2287 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2288 enumeration.reserve( values.size() );
2291 OGRCodedValue codedValue;
2292 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2293 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2294 enumeration.push_back( codedValue );
2297 last.pszCode =
nullptr;
2298 last.pszValue =
nullptr;
2299 enumeration.push_back( last );
2300 res = OGR_CodedFldDomain_Create(
2301 domain->
name().toUtf8().constData(),
2308 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2310 CPLFree( value.pszCode );
2311 CPLFree( value.pszValue );
2318 std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2319 std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2322 res = OGR_RangeFldDomain_Create(
2323 domain->
name().toUtf8().constData(),
2328 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2330 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2337 res = OGR_GlobFldDomain_Create(
2338 domain->
name().toUtf8().constData(),
2342 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2351 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2354 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2357 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2364 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2367 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2370 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2383#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2387 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2389 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2391 QVariantMap leftTableUriParts = datasetUriParts;
2392 leftTableUriParts.insert( QStringLiteral(
"layerName" ), leftTableName );
2393 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2395 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2396 QVariantMap rightTableUriParts = datasetUriParts;
2397 rightTableUriParts.insert( QStringLiteral(
"layerName" ), rightTableName );
2398 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2400 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2401 QString mappingTableSource;
2402 if ( !mappingTableName.isEmpty() )
2404 QVariantMap mappingTableUriParts = datasetUriParts;
2405 mappingTableUriParts.insert( QStringLiteral(
"layerName" ), mappingTableName );
2406 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2409 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2411 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2413 CSLDestroy( cslLeftTableFieldNames );
2415 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2417 CSLDestroy( cslRightTableFieldNames );
2419 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2421 CSLDestroy( cslLeftMappingTableFieldNames );
2423 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2425 CSLDestroy( cslRightMappingTableFieldNames );
2427 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2428 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2429 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2431 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2433 switch ( relationshipType )
2439 case GRT_ASSOCIATION:
2443 case GRT_AGGREGATION:
2444 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2448 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2450 switch ( eCardinality )
2452 case GRC_ONE_TO_ONE:
2455 case GRC_ONE_TO_MANY:
2458 case GRC_MANY_TO_ONE:
2461 case GRC_MANY_TO_MANY:
2466 switch ( cardinality )
2475 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2476 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2491 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2492 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2510 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2514 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2517 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2520 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2523 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2530 const QString leftTableName = leftParts.value( QStringLiteral(
"layerName" ) ).toString();
2531 if ( leftTableName.isEmpty() )
2533 error = QObject::tr(
"Parent table name was not set" );
2538 const QString rightTableName = rightParts.value( QStringLiteral(
"layerName" ) ).toString();
2539 if ( rightTableName.isEmpty() )
2541 error = QObject::tr(
"Child table name was not set" );
2545 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != rightParts.value( QStringLiteral(
"path" ) ).toString() )
2547 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2551 QString mappingTableName;
2555 mappingTableName = mappingParts.value( QStringLiteral(
"layerName" ) ).toString();
2556 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != mappingParts.value( QStringLiteral(
"path" ) ).toString() )
2558 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2564 leftTableName.toLocal8Bit().constData(),
2565 rightTableName.toLocal8Bit().constData(),
2570 int count = leftFieldNames.count();
2571 char **lst =
new char *[count + 1];
2575 for (
const QString &
string : leftFieldNames )
2577 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2581 lst[count] =
nullptr;
2582 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2587 count = rightFieldNames.count();
2588 lst =
new char *[count + 1];
2592 for (
const QString &
string : rightFieldNames )
2594 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2598 lst[count] =
nullptr;
2599 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2602 if ( !mappingTableName.isEmpty() )
2604 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2608 int count = leftFieldNames.count();
2609 char **lst =
new char *[count + 1];
2613 for (
const QString &
string : leftFieldNames )
2615 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2619 lst[count] =
nullptr;
2620 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2625 count = rightFieldNames.count();
2626 lst =
new char *[count + 1];
2630 for (
const QString &
string : rightFieldNames )
2632 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2636 lst[count] =
nullptr;
2637 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2645 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2649 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2655 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2657 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2661 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2669 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2673 errCause = QObject::tr(
"No styles available on DB" );
2677 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2680 errCause = QObject::tr(
"No styles available on DB" );
2684 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2686 OGR_L_ResetReading( hLayer );
2688 QList<qlonglong> listTimestamp;
2689 QMap<int, QString> mapIdToStyleName;
2690 QMap<int, QString> mapIdToDescription;
2691 QMap<qlonglong, QList<int> > mapTimestampToId;
2692 int numberOfRelatedStyles = 0;
2700 QString tableName( QString::fromUtf8(
2701 OGR_F_GetFieldAsString( hFeature.get(),
2702 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2703 QString geometryColumn( QString::fromUtf8(
2704 OGR_F_GetFieldAsString( hFeature.get(),
2705 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2706 QString styleName( QString::fromUtf8(
2707 OGR_F_GetFieldAsString( hFeature.get(),
2708 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2709 QString description( QString::fromUtf8(
2710 OGR_F_GetFieldAsString( hFeature.get(),
2711 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2712 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2713 if ( tableName == layerName &&
2714 geometryColumn == geomColumn )
2717 QString id( QString::number( fid ) );
2719 names.append( styleName );
2720 descriptions.append( description );
2721 ++ numberOfRelatedStyles;
2725 int year, month, day, hour, minute, second, TZ;
2726 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2727 &year, &month, &day, &hour, &minute, &second, &TZ );
2728 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2729 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2731 listTimestamp.append( ts );
2732 mapIdToStyleName[fid] = styleName;
2733 mapIdToDescription[fid] = description;
2734 mapTimestampToId[ts].append( fid );
2738 std::sort( listTimestamp.begin(), listTimestamp.end() );
2740 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2742 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2743 for (
int j = 0; j < listId.size(); j++ )
2745 int fid = listId[j];
2746 QString id( QString::number( fid ) );
2748 names.append( mapIdToStyleName[fid] );
2749 descriptions.append( mapIdToDescription[fid] );
2753 return numberOfRelatedStyles;
2761 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2765 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2767 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2768 " AND f_table_name=%1"
2769 " AND f_geometry_column=%2"
2770 " AND styleName=%3" )
2771 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2772 QgsOgrProviderUtils::quotedValue( geomColumn ),
2773 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2774 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2775 OGR_L_ResetReading( hLayer );
2777 OGR_L_ResetReading( hLayer );
2787 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2791 errCause = QObject::tr(
"No styles available on DB" );
2796 int id = styleId.toInt( &ok );
2799 errCause = QObject::tr(
"Invalid style identifier" );
2806 errCause = QObject::tr(
"No style corresponding to style identifier" );
2810 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2811 QString styleQML( QString::fromUtf8(
2812 OGR_F_GetFieldAsString( hFeature.get(),
2813 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2814 OGR_L_ResetReading( hLayer );
2823 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2828 errCause = QObject::tr(
"Connection to database failed" );
2833 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2835 errCause = QObject::tr(
"Error executing the delete query." );
2848 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2852 errCause = QObject::tr(
"No styles available on DB" );
2856 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2857 " AND f_table_name=%1"
2858 " AND f_geometry_column=%2"
2859 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2860 ",update_time DESC" )
2861 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2862 QgsOgrProviderUtils::quotedValue( geomColumn ) );
2863 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2864 OGR_L_ResetReading( hLayer );
2865 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2867 qlonglong moreRecentTimestamp = 0;
2873 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2875 styleQML = QString::fromUtf8(
2876 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2877 styleName = QString::fromUtf8(
2878 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2882 int year, month, day, hour, minute, second, TZ;
2883 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2884 &year, &month, &day, &hour, &minute, &second, &TZ );
2885 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2886 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2887 if ( ts > moreRecentTimestamp )
2889 moreRecentTimestamp = ts;
2890 styleQML = QString::fromUtf8(
2891 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2892 styleName = QString::fromUtf8(
2893 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2896 OGR_L_ResetReading( hLayer );
2902 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
2903 const QString &styleName,
const QString &styleDescription,
2904 const QString &uiFileContent,
bool useAsDefault, QString &errCause
2908 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2915 char **options =
nullptr;
2917 options = CSLSetNameValue( options,
"FID",
"id" );
2918 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
2919 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
2920 CSLDestroy( options );
2923 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2929 OGR_Fld_SetWidth( fld.get(), 256 );
2930 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2934 OGR_Fld_SetWidth( fld.get(), 256 );
2935 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2939 OGR_Fld_SetWidth( fld.get(), 256 );
2940 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2944 OGR_Fld_SetWidth( fld.get(), 256 );
2945 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2949 OGR_Fld_SetWidth( fld.get(), 30 );
2950 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2954 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2958 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2962 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
2963 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2967 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2971 OGR_Fld_SetWidth( fld.get(), 30 );
2972 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2976 OGR_Fld_SetWidth( fld.get(), 30 );
2977 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2981 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
2982 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2986 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2991 QString realStyleName =
2992 styleName.isEmpty() ? layerName : styleName;
2994 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2998 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
2999 " AND f_table_name=%1"
3000 " AND f_geometry_column=%2" )
3001 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3002 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
3003 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
3007 OGR_F_SetFieldInteger( hFeature.get(),
3008 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3010 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
3013 QgsDebugError( QStringLiteral(
"Could not unset previous useAsDefault style" ) );
3018 QString checkQuery = QStringLiteral(
"f_table_schema=''"
3019 " AND f_table_name=%1"
3020 " AND f_geometry_column=%2"
3021 " AND styleName=%3" )
3022 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3023 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
3024 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
3025 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
3026 OGR_L_ResetReading( hLayer );
3028 OGR_L_ResetReading( hLayer );
3037 hFeature.reset( OGR_F_Create( hLayerDefn ) );
3038 OGR_F_SetFieldString( hFeature.get(),
3039 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
3041 OGR_F_SetFieldString( hFeature.get(),
3042 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
3044 OGR_F_SetFieldString( hFeature.get(),
3045 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
3046 layerName.toUtf8().constData() );
3047 OGR_F_SetFieldString( hFeature.get(),
3048 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
3049 geomColumn.toUtf8().constData() );
3050 OGR_F_SetFieldString( hFeature.get(),
3051 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
3052 realStyleName.toUtf8().constData() );
3053 if ( !uiFileContent.isEmpty() )
3055 OGR_F_SetFieldString( hFeature.get(),
3056 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
3057 uiFileContent.toUtf8().constData() );
3060 OGR_F_SetFieldString( hFeature.get(),
3061 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3062 qmlStyle.toUtf8().constData() );
3063 OGR_F_SetFieldString( hFeature.get(),
3064 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3065 sldStyle.toUtf8().constData() );
3066 OGR_F_SetFieldInteger( hFeature.get(),
3067 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3068 useAsDefault ? 1 : 0 );
3069 OGR_F_SetFieldString( hFeature.get(),
3070 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3071 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3072 OGR_F_SetFieldString( hFeature.get(),
3073 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3078 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3080 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3085 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...
@ GeometryWeighted
New values are computed as the weighted average of the source values.
@ DefaultValue
Use default field value.
@ GeometryRatio
New values are computed by the ratio of their area/length compared to the area/length of the original...
@ UnsetField
Clears the field value so that the data provider backend will populate using any backend triggers or ...
@ DefaultValue
Use default field value.
@ Duplicate
Duplicate original value.
MarkerShape
Marker shapes.
@ Cross2
Rotated cross (lines only), 'x' shape.
@ Cross
Cross (lines only)
RenderUnit
Rendering size units.
@ 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.
@ MultiLineStringZM
MultiLineStringZM.
@ MultiPointZM
MultiPointZM.
@ MultiPointZ
MultiPointZ.
@ CompoundCurve
CompoundCurve.
@ MultiPolygonZM
MultiPolygonZM.
@ LineStringM
LineStringM.
@ MultiLineStringM
MultiLineStringM.
@ MultiPointM
MultiPointM.
@ LineStringZM
LineStringZM.
@ GeometryCollectionZM
GeometryCollectionZM.
@ CompoundCurveZM
CompoundCurveZM.
@ CompoundCurveM
CompoundCurveM.
@ MultiPolygon
MultiPolygon.
@ GeometryCollectionZ
GeometryCollectionZ.
@ GeometryCollectionM
GeometryCollectionM.
@ CircularStringZM
CircularStringZM.
@ MultiSurfaceZ
MultiSurfaceZ.
@ CurvePolygonZM
CurvePolygonZM.
@ MultiLineString
MultiLineString.
@ MultiPolygonM
MultiPolygonM.
@ MultiCurveZM
MultiCurveZM.
@ MultiSurfaceZM
MultiSurfaceZM.
@ CurvePolygonM
CurvePolygonM.
@ CircularString
CircularString.
@ MultiLineStringZ
MultiLineStringZ.
@ GeometryCollection
GeometryCollection.
@ MultiPolygonZ
MultiPolygonZ.
@ CurvePolygonZ
CurvePolygonZ.
@ CompoundCurveZ
CompoundCurveZ.
@ MultiCurveZ
MultiCurveZ.
@ MultiCurveM
MultiCurveM.
@ CircularStringM
CircularStringM.
@ CurvePolygon
CurvePolygon.
@ CircularStringZ
CircularStringZ.
@ LineStringZ
LineStringZ.
@ MultiSurface
MultiSurface.
@ 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.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
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.
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).
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
A geometry is the spatial representation of a feature.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static void warning(const QString &msg)
Goes to qWarning.
Context for a MapInfo symbol conversion operation.
static QgsFillSymbol * convertFillSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, const QColor &backColor=QColor())
Converts the MapInfo fill symbol with the specified identifier to a QgsFillSymbol.
static QgsMarkerSymbol * convertMarkerSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &color, double size, Qgis::RenderUnit sizeUnit)
Converts the MapInfo marker symbol with the specified identifier to a QgsMarkerSymbol.
static QgsLineSymbol * convertLineSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, double size, Qgis::RenderUnit sizeUnit, bool interleaved=false)
Converts the MapInfo line symbol with the specified identifier to a QgsLineSymbol.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QString readShapefileEncoding(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static QgsWeakRelation convertRelationship(GDALRelationshipH relationship, const QString &datasetUri)
Converts an GDAL relationship definition to a QgsWeakRelation equivalent.
static QVariant stringToVariant(OGRFieldType type, OGRFieldSubType subType, const QString &string)
Converts a string to a variant, using the provider OGR field type and subType to determine the most a...
static bool readOgrFeatureAttributes(OGRFeatureH ogrFet, const QgsFields &fields, QgsFeature &feature, QTextCodec *encoding)
Reads all attributes from an OGR feature into a QgsFeature.
static QString loadStoredStyle(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, QString &styleName, QString &errCause)
Helper function for loading a stored styles in ogr/gdal database datasources.
static QString getStyleById(GDALDatasetH hDS, const QString &styleId, QString &errCause)
Helper function for getting a style by ID from ogr/gdal database datasources.
static Qgis::WkbType ogrGeometryTypeToQgsWkbType(OGRwkbGeometryType ogrGeomType)
Converts a OGRwkbGeometryType to QgsWkbTypes::Type.
static int listStyles(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Helper function for listing styles in ogr/gdal database datasources.
static QgsGeometry ogrGeometryToQgsGeometry(OGRGeometryH geom)
Converts an OGR geometry representation to a QgsGeometry object.
static QString OGRSpatialReferenceToWkt(OGRSpatialReferenceH srs)
Returns a WKT string corresponding to the specified OGR srs object.
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
static bool saveStyle(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Helper function for saving a style to ogr/gdal database datasources.
static bool styleExists(GDALDatasetH hDS, const QString &layerName, const QString &geomColumn, const QString &styleId, QString &errorCause)
Helper function for checking whether a style exists in ogr/gdal database datasources.
static QVariant OGRFieldtoVariant(const OGRField *value, OGRFieldType type)
Converts an OGRField value of the specified type into a QVariant.
static QgsFeature readOgrFeature(OGRFeatureH ogrFet, const QgsFields &fields, QTextCodec *encoding)
Reads an OGR feature and converts it to a QgsFeature.
static QStringList cStringListToQStringList(char **stringList)
Converts a c string list to a QStringList.
static void ogrFieldTypeToQVariantType(OGRFieldType ogrType, OGRFieldSubType ogrSubType, QMetaType::Type &variantType, QMetaType::Type &variantSubType)
Converts an OGR field type and sub type to the best matching QVariant::Type equivalent.
static QgsFields readOgrFields(OGRFeatureH ogrFet, QTextCodec *encoding)
Reads an OGR feature and returns a corresponding fields collection.
static QList< QgsVectorDataProvider::NativeType > nativeFieldTypesForDriver(GDALDriverH driver)
Returns the list of native field types supported for a driver.
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static QgsCoordinateReferenceSystem OGRSpatialReferenceToCrs(OGRSpatialReferenceH srs)
Returns a QgsCoordinateReferenceSystem corresponding to the specified OGR srs object,...
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
static QString readShapefileEncodingFromCpg(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static bool readOgrFeatureGeometry(OGRFeatureH ogrFet, QgsFeature &feature)
Reads the geometry from an OGR feature into a QgsFeature.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
static QString readShapefileEncodingFromLdid(const QString &path)
Reads the encoding of the shapefile at the specified path (where path is the location of the "....
static std::unique_ptr< QgsSymbol > symbolFromStyleString(const QString &string, Qgis::SymbolType type)
Creates a new QgsSymbol matching an OGR style string.
static std::unique_ptr< OGRField > variantToOGRField(const QVariant &value, OGRFieldType type)
Converts a QVariant to an OGRField value of specified type.
static bool deleteStyleById(GDALDatasetH hDS, const QString &styleId, QString &errCause)
Helper function for deleting a style by id from ogr/gdal database datasources.
static void variantTypeToOgrFieldType(QMetaType::Type variantType, OGRFieldType &ogrType, OGRFieldSubType &ogrSubType)
Converts an QVariant type to the best matching OGR field type and sub type.
static QVariantMap parseStyleString(const QString &string)
Parses an OGR style string to a variant map containing the style string components.
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
static QVariant getOgrFeatureAttribute(OGRFeatureH ogrFet, const QgsFields &fields, int attIndex, QTextCodec *encoding, bool *ok=nullptr)
Retrieves an attribute value from an OGR feature.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
static bool shapeIsFilled(Qgis::MarkerShape shape)
Returns true if a symbol shape has a fill.
static bool condenseFillAndOutline(QgsFillSymbolLayer *fill, QgsLineSymbolLayer *outline)
Attempts to condense a fill and outline layer, by moving the outline layer to the fill symbol's strok...
static QString typeToDisplayString(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType)
Returns a user-friendly translated string representing a QVariant type.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
The QgsWeakRelation class represent a QgsRelation with possibly unresolved layers or unmatched fields...
void setMappingTable(const QgsVectorLayerRef &table)
Sets a weak reference to the mapping table, which forms the middle table in many-to-many relationship...
QStringList mappingReferencingLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
void setForwardPathLabel(const QString &label)
Sets the label of the forward path for the relationship.
QString mappingTableSource() const
Returns the source URI for the mapping table, which forms the middle table in many-to-many relationsh...
void setMappingReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
void setBackwardPathLabel(const QString &label)
Sets the label of the backward path for the relationship.
QString relatedTableType() const
Returns the type string of the related table.
void setReferencingLayerFields(const QStringList &fields)
Sets the list of fields from the referencingLayer() involved in the relationship.
QString name() const
Returns the relationship's name.
QString backwardPathLabel() const
Returns the label of the backward path for the relationship.
void setMappingReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the mappingTable() involved in the relationship.
QString referencedLayerSource() const
Returns the source URI for the referenced (or "parent" / "left") layer.
QString referencingLayerSource() const
Returns the source URI for the referencing (or "child" / "right") layer.
QString forwardPathLabel() const
Returns the label of the forward path for the relationship.
Qgis::RelationshipCardinality cardinality() const
Returns the relationship's cardinality.
void setCardinality(Qgis::RelationshipCardinality cardinality)
Sets the relationship's cardinality.
QStringList referencedLayerFields() const
Returns the list of fields from the referencedLayer() involved in the relationship.
QStringList mappingReferencedLayerFields() const
Returns the list of fields from the mappingTable() involved in the relationship.
void setRelatedTableType(const QString &type)
Sets the type string of the related table.
QStringList referencingLayerFields() const
Returns the list of fields from the referencingLayer() involved in the relationship.
void setReferencedLayerFields(const QStringList &fields)
Sets the list of fields from the referencedLayer() involved in the relationship.
Qgis::RelationshipStrength strength() const
Returns the strength of the relation.
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
void CORE_EXPORT fast_delete_and_close(dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path)
Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying data store.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
std::unique_ptr< std::remove_pointer< GDALRelationshipH >::type, GDALRelationshipDeleter > relationship_unique_ptr
Scoped GDAL relationship.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
void * OGRSpatialReferenceH
QList< QgsFeature > QgsFeatureList
#define DEFAULT_SIMPLELINE_WIDTH
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
#define DEFAULT_SIMPLEMARKER_SIZE
std::unique_ptr< QgsLineString > ogrGeometryToQgsLineString(OGRGeometryH geom)
std::unique_ptr< QgsMultiLineString > ogrGeometryToQgsMultiLineString(OGRGeometryH geom)
std::unique_ptr< QgsMultiPoint > ogrGeometryToQgsMultiPoint(OGRGeometryH geom)
std::unique_ptr< QgsPolygon > ogrGeometryToQgsPolygon(OGRGeometryH geom)
std::unique_ptr< QgsPoint > ogrGeometryToQgsPoint(OGRGeometryH geom)
std::unique_ptr< QgsMultiPolygon > ogrGeometryToQgsMultiPolygon(OGRGeometryH geom)
QList< QgsSymbolLayer * > QgsSymbolLayerList
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
const QgsCoordinateReferenceSystem & crs
void CORE_EXPORT operator()(GDALDatasetH datasource) const
Destroys an gdal dataset, using the correct gdal calls.
void CORE_EXPORT operator()(GDALRelationshipH relationship) const
Destroys GDAL relationship, using the correct gdal calls.
void CORE_EXPORT operator()(GDALWarpOptions *options) const
Destroys GDAL warp options, using the correct gdal calls.
void CORE_EXPORT operator()(OGRDataSourceH source) const
Destroys an OGR data source, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFeatureH feature) const
Destroys an OGR feature, using the correct gdal calls.
void CORE_EXPORT operator()(OGRFieldDefnH definition) const
Destroys an OGR field definition, using the correct gdal calls.
void CORE_EXPORT operator()(OGRGeometryH geometry) const
Destroys an OGR geometry, using the correct gdal calls.