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.type() )
242 case QVariant::Invalid:
243 OGR_RawField_SetUnset( res.get() );
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 )
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 QVariant::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 QVariant::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" );
347 case QVariant::String:
349 if ( type == OFTString )
350 res->String = CPLStrdup( value.toString().toUtf8().constData() );
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;
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 QVariant::DateTime:
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 QVariant::Type varType;
468 switch ( OGR_Fld_GetType( fldDef ) )
471 if ( OGR_Fld_GetSubType( fldDef ) == OFSTBoolean )
472 varType = QVariant::Bool;
474 varType = QVariant::Int;
477 varType = QVariant::LongLong;
480 varType = QVariant::Double;
483 varType = QVariant::Date;
486 varType = QVariant::Time;
489 varType = QVariant::DateTime;
492 if ( OGR_Fld_GetSubType( fldDef ) == OFSTJSON )
493 varType = QVariant::Map;
495 varType = QVariant::String;
498 varType = QVariant::String;
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 QVariant::String:
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(
"" ) );
565 value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) );
568 value = QVariant(
bool( OGR_F_GetFieldAsInteger( ogrFet, attIndex ) ) );
570 case QVariant::LongLong:
571 value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attIndex ) );
573 case QVariant::Double:
574 value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attIndex ) );
577 case QVariant::DateTime:
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() == QVariant::Date )
588 value = QDate( year, month, day );
589 else if ( field.
type() == QVariant::Time )
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 QVariant::ByteArray:
604 const GByte *b = OGR_F_GetFieldAsBinary( ogrFet, attIndex, &size );
608 QByteArray ba = QByteArray::fromRawData(
reinterpret_cast<const char *
>( b ), size );
615 case QVariant::StringList:
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] );
639 case QVariant::String:
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] );
663 const int *lst = OGR_F_GetFieldAsIntegerList( ogrFet, attIndex, &count );
666 list.reserve( count );
667 for (
int i = 0; i < count; i++ )
676 case QVariant::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 QVariant::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" );
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" );
739 value = QVariant( 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 = QVariant::Type::Invalid;
1886 variantSubType = QVariant::Type::Invalid;
1891 if ( ogrSubType == OFSTBoolean )
1893 variantType = QVariant::Bool;
1894 ogrSubType = OFSTBoolean;
1897 variantType = QVariant::Int;
1900 variantType = QVariant::LongLong;
1903 variantType = QVariant::Double;
1906 variantType = QVariant::Date;
1909 variantType = QVariant::Time;
1912 variantType = QVariant::DateTime;
1916 variantType = QVariant::ByteArray;
1921 if ( ogrSubType == OFSTJSON )
1923 ogrSubType = OFSTJSON;
1924 variantType = QVariant::Map;
1925 variantSubType = QVariant::String;
1929 variantType = QVariant::String;
1934 case OFTWideStringList:
1935 variantType = QVariant::StringList;
1936 variantSubType = QVariant::String;
1939 case OFTIntegerList:
1940 variantType = QVariant::List;
1941 variantSubType = QVariant::Int;
1945 variantType = QVariant::List;
1946 variantSubType = QVariant::Double;
1949 case OFTInteger64List:
1950 variantType = QVariant::List;
1951 variantSubType = QVariant::LongLong;
1958 ogrSubType = OFSTNone;
1959 switch ( variantType )
1961 case QVariant::Bool:
1962 ogrType = OFTInteger;
1963 ogrSubType = OFSTBoolean;
1967 ogrType = OFTInteger;
1970 case QVariant::LongLong:
1971 ogrType = OFTInteger64;
1974 case QVariant::Double:
1978 case QVariant::Char:
1979 ogrType = OFTString;
1982 case QVariant::String:
1983 ogrType = OFTString;
1986 case QVariant::StringList:
1987 ogrType = OFTStringList;
1990 case QVariant::ByteArray:
1991 ogrType = OFTBinary;
1994 case QVariant::Date:
1998 case QVariant::Time:
2001 case QVariant::DateTime:
2002 ogrType = OFTDateTime;
2006 ogrType = OFTString;
2013 if (
string.isEmpty() )
2021 res =
string.toInt( &ok );
2025 res =
string.toLongLong( &ok );
2029 res =
string.toDouble( &ok );
2039 res = QDate::fromString(
string, Qt::ISODate );
2044 res = QTime::fromString(
string, Qt::ISODate );
2049 res = QDateTime::fromString(
string, Qt::ISODate );
2059 return ok ? res : QVariant();
2067 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2069 int nMaxIntLen = 11;
2070 int nMaxInt64Len = 21;
2071 int nMaxDoubleLen = 20;
2072 int nMaxDoublePrec = 15;
2074 if ( driverName == QLatin1String(
"GPKG" ) )
2084 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2088 <<
QgsVectorDataProvider::NativeType( QObject::tr(
"Decimal number (real)" ), QStringLiteral(
"double" ), QVariant::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
2091 if ( driverName == QLatin1String(
"GPKG" ) )
2094 bool supportsDate =
true;
2095 bool supportsTime =
true;
2096 bool supportsDateTime =
true;
2097 bool supportsBinary =
false;
2098 bool supportIntegerList =
false;
2099 bool supportInteger64List =
false;
2100 bool supportRealList =
false;
2101 bool supportsStringList =
false;
2105 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2107 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2108 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2109 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2110 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2111 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2112 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2113 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2114 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2115 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2116 CSLDestroy( papszTokens );
2121#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2122 if ( driverName == QLatin1String(
"ESRI Shapefile" ) )
2124 supportsDateTime =
false;
2138 if ( supportsDateTime )
2143 if ( supportsBinary )
2148 if ( supportIntegerList )
2153 if ( supportInteger64List )
2158 if ( supportRealList )
2163 if ( supportsStringList )
2169 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2170 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2181#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2187 const QString name{ OGR_FldDomain_GetName( domain ) };
2188 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2190 QVariant::Type fieldType = QVariant::Type::Invalid;
2191 QVariant::Type fieldSubType = QVariant::Type::Invalid;
2192 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2193 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2194 ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
2196 std::unique_ptr< QgsFieldDomain > res;
2197 switch ( OGR_FldDomain_GetDomainType( domain ) )
2201 QList< QgsCodedValue > values;
2202 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2203 while ( codedValue && codedValue->pszCode )
2205 const QString code( codedValue->pszCode );
2210 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2211 values.append(
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
2216 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2223 bool minIsInclusive =
false;
2224 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2229 bool maxIsInclusive =
false;
2230 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2235 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2236 minValue, minIsInclusive,
2237 maxValue, maxIsInclusive );
2242 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2243 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2247 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2249 case OFDMP_DEFAULT_VALUE:
2255 case OFDMP_GEOMETRY_WEIGHTED:
2260 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2262 case OFDSP_DEFAULT_VALUE:
2265 case OFDSP_DUPLICATE:
2268 case OFDSP_GEOMETRY_RATIO:
2280 OGRFieldType domainFieldType = OFTInteger;
2281 OGRFieldSubType domainFieldSubType = OFSTNone;
2282 variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
2284 OGRFieldDomainH res =
nullptr;
2285 switch ( domain->
type() )
2289 std::vector< OGRCodedValue > enumeration;
2290 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2291 enumeration.reserve( values.size() );
2294 OGRCodedValue codedValue;
2295 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2296 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2297 enumeration.push_back( codedValue );
2300 last.pszCode =
nullptr;
2301 last.pszValue =
nullptr;
2302 enumeration.push_back( last );
2303 res = OGR_CodedFldDomain_Create(
2304 domain->
name().toUtf8().constData(),
2311 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2313 CPLFree( value.pszCode );
2314 CPLFree( value.pszValue );
2321 std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2322 std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2325 res = OGR_RangeFldDomain_Create(
2326 domain->
name().toUtf8().constData(),
2331 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2333 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2340 res = OGR_GlobFldDomain_Create(
2341 domain->
name().toUtf8().constData(),
2345 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2354 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2357 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2360 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2367 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2370 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2373 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2386#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2390 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2392 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2394 QVariantMap leftTableUriParts = datasetUriParts;
2395 leftTableUriParts.insert( QStringLiteral(
"layerName" ), leftTableName );
2396 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2398 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2399 QVariantMap rightTableUriParts = datasetUriParts;
2400 rightTableUriParts.insert( QStringLiteral(
"layerName" ), rightTableName );
2401 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2403 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2404 QString mappingTableSource;
2405 if ( !mappingTableName.isEmpty() )
2407 QVariantMap mappingTableUriParts = datasetUriParts;
2408 mappingTableUriParts.insert( QStringLiteral(
"layerName" ), mappingTableName );
2409 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2412 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2414 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2416 CSLDestroy( cslLeftTableFieldNames );
2418 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2420 CSLDestroy( cslRightTableFieldNames );
2422 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2424 CSLDestroy( cslLeftMappingTableFieldNames );
2426 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2428 CSLDestroy( cslRightMappingTableFieldNames );
2430 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2431 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2432 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2434 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2436 switch ( relationshipType )
2442 case GRT_ASSOCIATION:
2446 case GRT_AGGREGATION:
2447 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2451 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2453 switch ( eCardinality )
2455 case GRC_ONE_TO_ONE:
2458 case GRC_ONE_TO_MANY:
2461 case GRC_MANY_TO_ONE:
2464 case GRC_MANY_TO_MANY:
2469 switch ( cardinality )
2478 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2479 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2494 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2495 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2513 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2517 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2520 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2523 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2526 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2533 const QString leftTableName = leftParts.value( QStringLiteral(
"layerName" ) ).toString();
2534 if ( leftTableName.isEmpty() )
2536 error = QObject::tr(
"Parent table name was not set" );
2541 const QString rightTableName = rightParts.value( QStringLiteral(
"layerName" ) ).toString();
2542 if ( rightTableName.isEmpty() )
2544 error = QObject::tr(
"Child table name was not set" );
2548 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != rightParts.value( QStringLiteral(
"path" ) ).toString() )
2550 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2554 QString mappingTableName;
2558 mappingTableName = mappingParts.value( QStringLiteral(
"layerName" ) ).toString();
2559 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != mappingParts.value( QStringLiteral(
"path" ) ).toString() )
2561 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2567 leftTableName.toLocal8Bit().constData(),
2568 rightTableName.toLocal8Bit().constData(),
2573 int count = leftFieldNames.count();
2574 char **lst =
new char *[count + 1];
2578 for (
const QString &
string : leftFieldNames )
2580 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2584 lst[count] =
nullptr;
2585 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2590 count = rightFieldNames.count();
2591 lst =
new char *[count + 1];
2595 for (
const QString &
string : rightFieldNames )
2597 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2601 lst[count] =
nullptr;
2602 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2605 if ( !mappingTableName.isEmpty() )
2607 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2611 int count = leftFieldNames.count();
2612 char **lst =
new char *[count + 1];
2616 for (
const QString &
string : leftFieldNames )
2618 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2622 lst[count] =
nullptr;
2623 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2628 count = rightFieldNames.count();
2629 lst =
new char *[count + 1];
2633 for (
const QString &
string : rightFieldNames )
2635 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2639 lst[count] =
nullptr;
2640 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2648 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2652 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2658 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2660 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2664 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2672 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2676 errCause = QObject::tr(
"No styles available on DB" );
2680 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2683 errCause = QObject::tr(
"No styles available on DB" );
2687 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2689 OGR_L_ResetReading( hLayer );
2691 QList<qlonglong> listTimestamp;
2692 QMap<int, QString> mapIdToStyleName;
2693 QMap<int, QString> mapIdToDescription;
2694 QMap<qlonglong, QList<int> > mapTimestampToId;
2695 int numberOfRelatedStyles = 0;
2703 QString tableName( QString::fromUtf8(
2704 OGR_F_GetFieldAsString( hFeature.get(),
2705 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2706 QString geometryColumn( QString::fromUtf8(
2707 OGR_F_GetFieldAsString( hFeature.get(),
2708 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2709 QString styleName( QString::fromUtf8(
2710 OGR_F_GetFieldAsString( hFeature.get(),
2711 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2712 QString description( QString::fromUtf8(
2713 OGR_F_GetFieldAsString( hFeature.get(),
2714 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2715 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2716 if ( tableName == layerName &&
2717 geometryColumn == geomColumn )
2720 QString id( QString::number( fid ) );
2722 names.append( styleName );
2723 descriptions.append( description );
2724 ++ numberOfRelatedStyles;
2728 int year, month, day, hour, minute, second, TZ;
2729 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2730 &year, &month, &day, &hour, &minute, &second, &TZ );
2731 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2732 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2734 listTimestamp.append( ts );
2735 mapIdToStyleName[fid] = styleName;
2736 mapIdToDescription[fid] = description;
2737 mapTimestampToId[ts].append( fid );
2741 std::sort( listTimestamp.begin(), listTimestamp.end() );
2743 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2745 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2746 for (
int j = 0; j < listId.size(); j++ )
2748 int fid = listId[j];
2749 QString id( QString::number( fid ) );
2751 names.append( mapIdToStyleName[fid] );
2752 descriptions.append( mapIdToDescription[fid] );
2756 return numberOfRelatedStyles;
2764 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2768 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2770 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2771 " AND f_table_name=%1"
2772 " AND f_geometry_column=%2"
2773 " AND styleName=%3" )
2774 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2775 QgsOgrProviderUtils::quotedValue( geomColumn ),
2776 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2777 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2778 OGR_L_ResetReading( hLayer );
2780 OGR_L_ResetReading( hLayer );
2790 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2794 errCause = QObject::tr(
"No styles available on DB" );
2799 int id = styleId.toInt( &ok );
2802 errCause = QObject::tr(
"Invalid style identifier" );
2809 errCause = QObject::tr(
"No style corresponding to style identifier" );
2813 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2814 QString styleQML( QString::fromUtf8(
2815 OGR_F_GetFieldAsString( hFeature.get(),
2816 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2817 OGR_L_ResetReading( hLayer );
2826 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2831 errCause = QObject::tr(
"Connection to database failed" );
2836 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2838 errCause = QObject::tr(
"Error executing the delete query." );
2851 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2855 errCause = QObject::tr(
"No styles available on DB" );
2859 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2860 " AND f_table_name=%1"
2861 " AND f_geometry_column=%2"
2862 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2863 ",update_time DESC LIMIT 1" )
2864 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
2865 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
2866 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2867 OGR_L_ResetReading( hLayer );
2868 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2870 qlonglong moreRecentTimestamp = 0;
2876 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2878 styleQML = QString::fromUtf8(
2879 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2880 styleName = QString::fromUtf8(
2881 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2885 int year, month, day, hour, minute, second, TZ;
2886 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2887 &year, &month, &day, &hour, &minute, &second, &TZ );
2888 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2889 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2890 if ( ts > moreRecentTimestamp )
2892 moreRecentTimestamp = ts;
2893 styleQML = QString::fromUtf8(
2894 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2895 styleName = QString::fromUtf8(
2896 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2899 OGR_L_ResetReading( hLayer );
2905 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
2906 const QString &styleName,
const QString &styleDescription,
2907 const QString &uiFileContent,
bool useAsDefault, QString &errCause
2911 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2918 char **options =
nullptr;
2920 options = CSLSetNameValue( options,
"FID",
"id" );
2921 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
2922 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
2923 CSLDestroy( options );
2926 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2932 OGR_Fld_SetWidth( fld.get(), 256 );
2933 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2937 OGR_Fld_SetWidth( fld.get(), 256 );
2938 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2942 OGR_Fld_SetWidth( fld.get(), 256 );
2943 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2947 OGR_Fld_SetWidth( fld.get(), 256 );
2948 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2952 OGR_Fld_SetWidth( fld.get(), 30 );
2953 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2957 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2961 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2965 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
2966 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2970 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2974 OGR_Fld_SetWidth( fld.get(), 30 );
2975 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2979 OGR_Fld_SetWidth( fld.get(), 30 );
2980 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2984 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
2985 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2989 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2994 QString realStyleName =
2995 styleName.isEmpty() ? layerName : styleName;
2997 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
3001 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
3002 " AND f_table_name=%1"
3003 " AND f_geometry_column=%2" )
3004 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3005 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
3006 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
3010 OGR_F_SetFieldInteger( hFeature.get(),
3011 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3013 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
3016 QgsDebugError( QStringLiteral(
"Could not unset previous useAsDefault style" ) );
3021 QString checkQuery = QStringLiteral(
"f_table_schema=''"
3022 " AND f_table_name=%1"
3023 " AND f_geometry_column=%2"
3024 " AND styleName=%3" )
3025 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
3026 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
3027 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
3028 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
3029 OGR_L_ResetReading( hLayer );
3031 OGR_L_ResetReading( hLayer );
3040 hFeature.reset( OGR_F_Create( hLayerDefn ) );
3041 OGR_F_SetFieldString( hFeature.get(),
3042 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
3044 OGR_F_SetFieldString( hFeature.get(),
3045 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
3047 OGR_F_SetFieldString( hFeature.get(),
3048 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
3049 layerName.toUtf8().constData() );
3050 OGR_F_SetFieldString( hFeature.get(),
3051 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
3052 geomColumn.toUtf8().constData() );
3053 OGR_F_SetFieldString( hFeature.get(),
3054 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
3055 realStyleName.toUtf8().constData() );
3056 if ( !uiFileContent.isEmpty() )
3058 OGR_F_SetFieldString( hFeature.get(),
3059 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
3060 uiFileContent.toUtf8().constData() );
3063 OGR_F_SetFieldString( hFeature.get(),
3064 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3065 qmlStyle.toUtf8().constData() );
3066 OGR_F_SetFieldString( hFeature.get(),
3067 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3068 sldStyle.toUtf8().constData() );
3069 OGR_F_SetFieldInteger( hFeature.get(),
3070 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3071 useAsDefault ? 1 : 0 );
3072 OGR_F_SetFieldString( hFeature.get(),
3073 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3074 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3075 OGR_F_SetFieldString( hFeature.get(),
3076 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3081 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3083 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3088 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.
SymbolType
Attribute editing capabilities which may be supported by vector data providers.
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.
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.
void setCoordinateEpoch(double epoch)
Sets the coordinate epoch, as a decimal year.
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
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.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
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.
virtual Qgis::FieldDomainType type() const =0
Returns the type of field domain.
QString name() const
Returns the name of the field domain.
QVariant::Type fieldType() const
Returns the associated field type.
QString description() const
Returns the description of the field domain.
Encapsulate a field in an attribute table or data source.
QVariant::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, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
int count() const
Returns number of items.
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 void variantTypeToOgrFieldType(QVariant::Type variantType, OGRFieldType &ogrType, OGRFieldSubType &ogrSubType)
Converts an QVariant type to the best matching OGR field type and sub type.
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 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 void ogrFieldTypeToQVariantType(OGRFieldType ogrType, OGRFieldSubType ogrSubType, QVariant::Type &variantType, QVariant::Type &variantSubType)
Converts an OGR field type and sub type to the best matching QVariant::Type equivalent.
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 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(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns a user-friendly translated string representing a QVariant type.
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 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.