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];
1035 if (
string.isEmpty() )
1038 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1041 QByteArray ba =
string.toUtf8();
1042 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1043 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1048 VSIUnlink( randomFileName.toUtf8().constData() );
1052 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1056 VSIUnlink( randomFileName.toUtf8().constData() );
1061 while ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1063 QgsFeature feat = readOgrFeature( oFeat.get(), fields, encoding );
1069 VSIUnlink( randomFileName.toUtf8().constData() );
1077 if (
string.isEmpty() )
1080 QString randomFileName = QStringLiteral(
"/vsimem/%1" ).arg( QUuid::createUuid().toString() );
1083 QByteArray ba =
string.toUtf8();
1084 VSIFCloseL( VSIFileFromMemBuffer( randomFileName.toUtf8().constData(),
reinterpret_cast< GByte *
>( ba.data() ),
1085 static_cast< vsi_l_offset
>( ba.size() ), FALSE ) );
1090 VSIUnlink( randomFileName.toUtf8().constData() );
1094 OGRLayerH ogrLayer = OGR_DS_GetLayer( hDS.get(), 0 );
1098 VSIUnlink( randomFileName.toUtf8().constData() );
1104 if ( oFeat.reset( OGR_L_GetNextFeature( ogrLayer ) ), oFeat )
1106 fields = readOgrFields( oFeat.get(), encoding );
1110 VSIUnlink( randomFileName.toUtf8().constData() );
1119 QStringList strings;
1121 for (
qgssize i = 0; stringList[i]; ++i )
1123 strings.
append( QString::fromUtf8( stringList[i] ) );
1134 char *pszWkt =
nullptr;
1135 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=NO" ).toLocal8Bit();
1136 const QByteArray formatOption = QStringLiteral(
"FORMAT=WKT2" ).toLocal8Bit();
1137 const char *
const options[] = {multiLineOption.constData(), formatOption.constData(),
nullptr};
1138 OSRExportToWktEx( srs, &pszWkt, options );
1140 const QString res( pszWkt );
1147 const QString wkt = OGRSpatialReferenceToWkt( srs );
1148 if ( wkt.isEmpty() )
1151 const char *authorityName = OSRGetAuthorityName( srs,
nullptr );
1152 const char *authorityCode = OSRGetAuthorityCode( srs,
nullptr );
1154 if ( authorityName && authorityCode )
1156 QString authId = QString( authorityName ) +
':' + QString( authorityCode );
1159 if ( OSRSetFromUserInput( ogrSrsTmp, authId.toUtf8().constData() ) != OGRERR_NONE &&
1160 OSRIsSame( srs, ogrSrsTmp ) )
1165 OSRDestroySpatialReference( ogrSrsTmp );
1170#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1171 const double coordinateEpoch = OSRGetCoordinateEpoch( srs );
1172 if ( coordinateEpoch > 0 )
1190 if ( !authId.isEmpty() )
1192 ogrSrs = OSRNewSpatialReference(
nullptr );
1193 if ( OSRSetFromUserInput( ogrSrs, authId.toUtf8().constData() ) == OGRERR_NONE )
1197 if ( ogrSrsFromWkt )
1199 if ( !OSRIsSame( ogrSrs, ogrSrsFromWkt ) )
1201 OSRDestroySpatialReference( ogrSrs );
1202 ogrSrs = ogrSrsFromWkt;
1206 OSRDestroySpatialReference( ogrSrsFromWkt );
1212 OSRDestroySpatialReference( ogrSrs );
1218 ogrSrs = OSRNewSpatialReference( srsWkt.toUtf8().constData() );
1222 OSRSetAxisMappingStrategy( ogrSrs, OAMS_TRADITIONAL_GIS_ORDER );
1223#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
1238 const QString cpgEncoding = readShapefileEncodingFromCpg( path );
1239 if ( !cpgEncoding.isEmpty() )
1242 return readShapefileEncodingFromLdid( path );
1248 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1249 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_CPG" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1255 QgsOgrLayerUniquePtr layer = QgsOgrProviderUtils::getLayer( path,
false, QStringList(), 0, errCause,
false );
1256 return layer ? layer->GetMetadataItem( QStringLiteral(
"ENCODING_FROM_LDID" ), QStringLiteral(
"SHAPEFILE" ) ) : QString();
1263 char **papszStyleString = CSLTokenizeString2(
string.toUtf8().constData(),
";",
1265 | CSLT_PRESERVEQUOTES
1266 | CSLT_PRESERVEESCAPES );
1267 for (
int i = 0; papszStyleString[i] !=
nullptr; ++i )
1273 const thread_local QRegularExpression sToolPartRx( QStringLiteral(
"^(.*?)\\((.*)\\)$" ) );
1274 const QString stylePart( papszStyleString[i] );
1275 const QRegularExpressionMatch match = sToolPartRx.match( stylePart );
1276 if ( !match.hasMatch() )
1279 const QString tool = match.captured( 1 );
1280 const QString params = match.captured( 2 );
1282 char **papszTokens = CSLTokenizeString2( params.toUtf8().constData(),
",", CSLT_HONOURSTRINGS
1283 | CSLT_PRESERVEESCAPES );
1285 QVariantMap toolParts;
1286 const thread_local QRegularExpression sToolParamRx( QStringLiteral(
"^(.*?):(.*)$" ) );
1287 for (
int j = 0; papszTokens[j] !=
nullptr; ++j )
1289 const QString toolPart( papszTokens[j] );
1290 const QRegularExpressionMatch toolMatch = sToolParamRx.match( toolPart );
1291 if ( !match.hasMatch() )
1295 toolParts.insert( toolMatch.captured( 1 ).toLower(), toolMatch.captured( 2 ) );
1297 CSLDestroy( papszTokens );
1300 styles.insert( tool.toLower(), toolParts );
1302 CSLDestroy( papszStyleString );
1308 const QVariantMap styles = parseStyleString(
string );
1310 auto convertSize = [](
const QString & size,
double & value,
Qgis::RenderUnit & unit )->
bool
1312 const thread_local QRegularExpression sUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.]+)(g|px|pt|mm|cm|in)$" ) );
1313 const QRegularExpressionMatch match = sUnitRx.match( size );
1314 if ( match.hasMatch() )
1316 value = match.captured( 1 ).toDouble();
1317 const QString unitString = match.captured( 2 );
1318 if ( unitString.compare( QLatin1String(
"px" ), Qt::CaseInsensitive ) == 0 )
1322 static constexpr double PT_TO_INCHES_FACTOR = 1 / 72.0;
1323 static constexpr double PX_TO_PT_FACTOR = 1 / ( 96.0 * PT_TO_INCHES_FACTOR );
1325 value *= PX_TO_PT_FACTOR;
1328 else if ( unitString.compare( QLatin1String(
"pt" ), Qt::CaseInsensitive ) == 0 )
1333 else if ( unitString.compare( QLatin1String(
"mm" ), Qt::CaseInsensitive ) == 0 )
1338 else if ( unitString.compare( QLatin1String(
"cm" ), Qt::CaseInsensitive ) == 0 )
1344 else if ( unitString.compare( QLatin1String(
"in" ), Qt::CaseInsensitive ) == 0 )
1349 else if ( unitString.compare( QLatin1String(
"g" ), Qt::CaseInsensitive ) == 0 )
1354 QgsDebugError( QStringLiteral(
"Unknown unit %1" ).arg( unitString ) );
1358 QgsDebugError( QStringLiteral(
"Could not parse style size %1" ).arg( size ) );
1363 auto convertColor = [](
const QString & string ) -> QColor
1365 if (
string.isEmpty() )
1368 const thread_local QRegularExpression sColorWithAlphaRx = QRegularExpression( QStringLiteral(
"^#([0-9a-fA-F]{6})([0-9a-fA-F]{2})$" ) );
1369 const QRegularExpressionMatch match = sColorWithAlphaRx.match(
string );
1370 if ( match.hasMatch() )
1373 return QColor( QStringLiteral(
"#%1%2" ).arg( match.captured( 2 ), match.captured( 1 ) ) );
1377 return QColor(
string );
1381 auto convertPen = [&convertColor, &convertSize, string](
const QVariantMap & lineStyle ) -> std::unique_ptr< QgsSymbol >
1383 QColor color = convertColor( lineStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1387 convertSize( lineStyle.value( QStringLiteral(
"w" ) ).toString(), lineWidth, lineWidthUnit );
1390 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-pen-(\\d+)" ) );
1391 const QRegularExpressionMatch match = sMapInfoId.match(
string );
1392 if ( match.hasMatch() )
1394 const int penId = match.captured( 1 ).toInt();
1401 std::unique_ptr< QgsSimpleLineSymbolLayer > simpleLine = std::make_unique< QgsSimpleLineSymbolLayer >( color, lineWidth );
1402 simpleLine->setWidthUnit( lineWidthUnit );
1405 const QString pattern = lineStyle.value( QStringLiteral(
"p" ) ).toString();
1406 if ( !pattern.isEmpty() )
1408 const thread_local QRegularExpression sPatternUnitRx = QRegularExpression( QStringLiteral(
"^([\\d\\.\\s]+)(g|px|pt|mm|cm|in)$" ) );
1409 const QRegularExpressionMatch match = sPatternUnitRx.match( pattern );
1410 if ( match.hasMatch() )
1412 const QStringList patternValues = match.captured( 1 ).split(
' ' );
1413 QVector< qreal > dashPattern;
1415 for (
const QString &val : patternValues )
1418 convertSize( val + match.captured( 2 ), length, patternUnits );
1419 dashPattern.push_back( length * lineWidth * 2 );
1422 simpleLine->setCustomDashVector( dashPattern );
1423 simpleLine->setCustomDashPatternUnit( patternUnits );
1424 simpleLine->setUseCustomDashPattern(
true );
1428 Qt::PenCapStyle capStyle = Qt::FlatCap;
1429 Qt::PenJoinStyle joinStyle = Qt::MiterJoin;
1431 const QString
id = lineStyle.value( QStringLiteral(
"id" ) ).toString();
1432 if (
id.contains( QLatin1String(
"mapinfo-pen" ), Qt::CaseInsensitive ) )
1437 capStyle = Qt::RoundCap;
1438 joinStyle = Qt::RoundJoin;
1442 const QString penCap = lineStyle.value( QStringLiteral(
"cap" ) ).toString();
1443 if ( penCap.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1445 capStyle = Qt::FlatCap;
1447 else if ( penCap.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1449 capStyle = Qt::RoundCap;
1451 else if ( penCap.compare( QLatin1String(
"p" ), Qt::CaseInsensitive ) == 0 )
1453 capStyle = Qt::SquareCap;
1455 simpleLine->setPenCapStyle( capStyle );
1458 const QString penJoin = lineStyle.value( QStringLiteral(
"j" ) ).toString();
1459 if ( penJoin.compare( QLatin1String(
"m" ), Qt::CaseInsensitive ) == 0 )
1461 joinStyle = Qt::MiterJoin;
1463 else if ( penJoin.compare( QLatin1String(
"r" ), Qt::CaseInsensitive ) == 0 )
1465 joinStyle = Qt::RoundJoin;
1467 else if ( penJoin.compare( QLatin1String(
"b" ), Qt::CaseInsensitive ) == 0 )
1469 joinStyle = Qt::BevelJoin;
1471 simpleLine->setPenJoinStyle( joinStyle );
1473 const QString priority = lineStyle.value( QStringLiteral(
"l" ) ).toString();
1474 if ( !priority.isEmpty() )
1476 simpleLine->setRenderingPass( priority.toInt() );
1478 return std::make_unique< QgsLineSymbol >(
QgsSymbolLayerList() << simpleLine.release() );
1481 auto convertBrush = [&convertColor](
const QVariantMap & brushStyle ) -> std::unique_ptr< QgsSymbol >
1483 const QColor foreColor = convertColor( brushStyle.value( QStringLiteral(
"fc" ), QStringLiteral(
"#000000" ) ).toString() );
1484 const QColor backColor = convertColor( brushStyle.value( QStringLiteral(
"bc" ), QString() ).toString() );
1486 const QString
id = brushStyle.value( QStringLiteral(
"id" ) ).toString();
1489 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-brush-(\\d+)" ) );
1490 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1491 if ( match.hasMatch() )
1493 const int brushId = match.captured( 1 ).toInt();
1500 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-brush-(\\d+)" ) );
1501 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1503 Qt::BrushStyle style = Qt::SolidPattern;
1504 if ( ogrMatch.hasMatch() )
1506 const int brushId = ogrMatch.captured( 1 ).toInt();
1510 style = Qt::SolidPattern;
1514 style = Qt::NoBrush;
1518 style = Qt::HorPattern;
1522 style = Qt::VerPattern;
1526 style = Qt::FDiagPattern;
1530 style = Qt::BDiagPattern;
1534 style = Qt::CrossPattern;
1538 style = Qt::DiagCrossPattern;
1544 if ( backColor.isValid() && style != Qt::SolidPattern && style != Qt::NoBrush )
1546 std::unique_ptr< QgsSimpleFillSymbolLayer > backgroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( backColor );
1547 backgroundFill->setLocked(
true );
1548 backgroundFill->setStrokeStyle( Qt::NoPen );
1549 layers << backgroundFill.release();
1552 std::unique_ptr< QgsSimpleFillSymbolLayer > foregroundFill = std::make_unique< QgsSimpleFillSymbolLayer >( foreColor );
1553 foregroundFill->setBrushStyle( style );
1554 foregroundFill->setStrokeStyle( Qt::NoPen );
1556 const QString priority = brushStyle.value( QStringLiteral(
"l" ) ).toString();
1557 if ( !priority.isEmpty() )
1559 foregroundFill->setRenderingPass( priority.toInt() );
1561 layers << foregroundFill.release();
1562 return std::make_unique< QgsFillSymbol >( layers );
1565 auto convertSymbol = [&convertColor, &convertSize, string](
const QVariantMap & symbolStyle ) -> std::unique_ptr< QgsSymbol >
1567 const QColor color = convertColor( symbolStyle.value( QStringLiteral(
"c" ), QStringLiteral(
"#000000" ) ).toString() );
1571 convertSize( symbolStyle.value( QStringLiteral(
"s" ) ).toString(), symbolSize, symbolSizeUnit );
1573 const double angle = symbolStyle.value( QStringLiteral(
"a" ), QStringLiteral(
"0" ) ).toDouble();
1575 const QString
id = symbolStyle.value( QStringLiteral(
"id" ) ).toString();
1578 const thread_local QRegularExpression sMapInfoId = QRegularExpression( QStringLiteral(
"mapinfo-sym-(\\d+)" ) );
1579 const QRegularExpressionMatch match = sMapInfoId.match(
id );
1580 if ( match.hasMatch() )
1582 const int symbolId = match.captured( 1 ).toInt();
1593 std::unique_ptr< QgsMarkerSymbolLayer > markerLayer;
1595 const thread_local QRegularExpression sFontId = QRegularExpression( QStringLiteral(
"font-sym-(\\d+)" ) );
1596 const QRegularExpressionMatch fontMatch = sFontId.match(
id );
1597 if ( fontMatch.hasMatch() )
1599 const int symId = fontMatch.captured( 1 ).toInt();
1600 const QStringList families = symbolStyle.value( QStringLiteral(
"f" ), QString() ).toString().split(
',' );
1602 bool familyFound =
false;
1605 for (
const QString &family : std::as_const( families ) )
1613 fontFamily = processedFamily;
1620 std::unique_ptr< QgsFontMarkerSymbolLayer > fontMarker = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, QChar( symId ), symbolSize );
1621 fontMarker->setSizeUnit( symbolSizeUnit );
1622 fontMarker->setAngle( -angle );
1624 fontMarker->setColor( color );
1626 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1627 if ( strokeColor.isValid() )
1629 fontMarker->setStrokeColor( strokeColor );
1630 fontMarker->setStrokeWidth( 1 );
1635 fontMarker->setStrokeWidth( 0 );
1638 markerLayer = std::move( fontMarker );
1640 else if ( !families.empty() )
1649 const thread_local QRegularExpression sOgrId = QRegularExpression( QStringLiteral(
"ogr-sym-(\\d+)" ) );
1650 const QRegularExpressionMatch ogrMatch = sOgrId.match(
id );
1653 bool isFilled =
true;
1654 if ( ogrMatch.hasMatch() )
1656 const int symId = ogrMatch.captured( 1 ).toInt();
1719 std::unique_ptr< QgsSimpleMarkerSymbolLayer > simpleMarker = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, symbolSize, -angle );
1720 simpleMarker->setSizeUnit( symbolSizeUnit );
1721 simpleMarker->setStrokeWidth( 1.0 );
1726 simpleMarker->setColor( color );
1727 simpleMarker->setStrokeStyle( Qt::NoPen );
1731 simpleMarker->setFillColor( QColor( 0, 0, 0, 0 ) );
1732 simpleMarker->setStrokeColor( color );
1735 const QColor strokeColor = convertColor( symbolStyle.value( QStringLiteral(
"o" ), QString() ).toString() );
1736 if ( strokeColor.isValid() )
1738 simpleMarker->setStrokeColor( strokeColor );
1739 simpleMarker->setStrokeStyle( Qt::SolidLine );
1742 markerLayer = std::move( simpleMarker );
1745 return std::make_unique< QgsMarkerSymbol >(
QgsSymbolLayerList() << markerLayer.release() );
1751 if ( styles.contains( QStringLiteral(
"symbol" ) ) )
1753 const QVariantMap symbolStyle = styles.value( QStringLiteral(
"symbol" ) ).toMap();
1754 return convertSymbol( symbolStyle );
1762 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1765 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1766 return convertPen( lineStyle );
1775 std::unique_ptr< QgsSymbol > fillSymbol = std::make_unique< QgsFillSymbol >();
1776 if ( styles.contains( QStringLiteral(
"brush" ) ) )
1778 const QVariantMap brushStyle = styles.value( QStringLiteral(
"brush" ) ).toMap();
1779 fillSymbol = convertBrush( brushStyle );
1783 std::unique_ptr< QgsSimpleFillSymbolLayer > emptyFill = std::make_unique< QgsSimpleFillSymbolLayer >();
1784 emptyFill->setBrushStyle( Qt::NoBrush );
1785 fillSymbol = std::make_unique< QgsFillSymbol >(
QgsSymbolLayerList() << emptyFill.release() );
1788 std::unique_ptr< QgsSymbol > penSymbol;
1789 if ( styles.contains( QStringLiteral(
"pen" ) ) )
1791 const QVariantMap lineStyle = styles.value( QStringLiteral(
"pen" ) ).toMap();
1792 penSymbol = convertPen( lineStyle );
1797 const int count = penSymbol->symbolLayerCount();
1807 for (
int i = 0; i < count; ++i )
1809 std::unique_ptr< QgsSymbolLayer > layer( penSymbol->takeSymbolLayer( 0 ) );
1810 layer->setLocked(
true );
1811 fillSymbol->appendSymbolLayer( layer.release() );
1827 variantType = QMetaType::Type::UnknownType;
1828 variantSubType = QMetaType::Type::UnknownType;
1833 if ( ogrSubType == OFSTBoolean )
1835 variantType = QMetaType::Type::Bool;
1836 ogrSubType = OFSTBoolean;
1839 variantType = QMetaType::Type::Int;
1842 variantType = QMetaType::Type::LongLong;
1845 variantType = QMetaType::Type::Double;
1848 variantType = QMetaType::Type::QDate;
1851 variantType = QMetaType::Type::QTime;
1854 variantType = QMetaType::Type::QDateTime;
1858 variantType = QMetaType::Type::QByteArray;
1863 if ( ogrSubType == OFSTJSON )
1865 ogrSubType = OFSTJSON;
1866 variantType = QMetaType::Type::QVariantMap;
1867 variantSubType = QMetaType::Type::QString;
1871 variantType = QMetaType::Type::QString;
1876 case OFTWideStringList:
1877 variantType = QMetaType::Type::QStringList;
1878 variantSubType = QMetaType::Type::QString;
1881 case OFTIntegerList:
1882 variantType = QMetaType::Type::QVariantList;
1883 variantSubType = QMetaType::Type::Int;
1887 variantType = QMetaType::Type::QVariantList;
1888 variantSubType = QMetaType::Type::Double;
1891 case OFTInteger64List:
1892 variantType = QMetaType::Type::QVariantList;
1893 variantSubType = QMetaType::Type::LongLong;
1900 ogrSubType = OFSTNone;
1901 switch ( variantType )
1903 case QMetaType::Type::Bool:
1904 ogrType = OFTInteger;
1905 ogrSubType = OFSTBoolean;
1908 case QMetaType::Type::Int:
1909 ogrType = OFTInteger;
1912 case QMetaType::Type::LongLong:
1913 ogrType = OFTInteger64;
1916 case QMetaType::Type::Double:
1920 case QMetaType::Type::QChar:
1921 case QMetaType::Type::QString:
1922 ogrType = OFTString;
1925 case QMetaType::Type::QStringList:
1926 ogrType = OFTStringList;
1929 case QMetaType::Type::QByteArray:
1930 ogrType = OFTBinary;
1933 case QMetaType::Type::QDate:
1937 case QMetaType::Type::QTime:
1940 case QMetaType::Type::QDateTime:
1941 ogrType = OFTDateTime;
1945 ogrType = OFTString;
1952 if (
string.isEmpty() )
1960 res =
string.toInt( &ok );
1964 res =
string.toLongLong( &ok );
1968 res =
string.toDouble( &ok );
1978 res = QDate::fromString(
string, Qt::ISODate );
1983 res = QTime::fromString(
string, Qt::ISODate );
1988 res = QDateTime::fromString(
string, Qt::ISODate );
1998 return ok ? res : QVariant();
2006 const QString driverName = QString::fromUtf8( GDALGetDriverShortName( driver ) );
2008 int nMaxIntLen = 11;
2009 int nMaxInt64Len = 21;
2010 int nMaxDoubleLen = 20;
2011 int nMaxDoublePrec = 15;
2013 if ( driverName == QLatin1String(
"GPKG" ) )
2023 QList<QgsVectorDataProvider::NativeType> nativeTypes;
2027 <<
QgsVectorDataProvider::NativeType( QObject::tr(
"Decimal number (real)" ), QStringLiteral(
"double" ), QMetaType::Type::Double, 0, nMaxDoubleLen, 0, nMaxDoublePrec )
2030 if ( driverName == QLatin1String(
"GPKG" ) )
2031 nativeTypes <<
QgsVectorDataProvider::NativeType( QObject::tr(
"JSON (string)" ), QStringLiteral(
"JSON" ), QMetaType::Type::QVariantMap, 0, 0, 0, 0, QMetaType::Type::QString );
2033 bool supportsDate =
true;
2034 bool supportsTime =
true;
2035 bool supportsDateTime =
true;
2036 bool supportsBinary =
false;
2037 bool supportIntegerList =
false;
2038 bool supportInteger64List =
false;
2039 bool supportRealList =
false;
2040 bool supportsStringList =
false;
2044 if (
const char *pszDataTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr ) )
2046 char **papszTokens = CSLTokenizeString2( pszDataTypes,
" ", 0 );
2047 supportsDate = CSLFindString( papszTokens,
"Date" ) >= 0;
2048 supportsTime = CSLFindString( papszTokens,
"Time" ) >= 0;
2049 supportsDateTime = CSLFindString( papszTokens,
"DateTime" ) >= 0;
2050 supportsBinary = CSLFindString( papszTokens,
"Binary" ) >= 0;
2051 supportIntegerList = CSLFindString( papszTokens,
"IntegerList" ) >= 0;
2052 supportInteger64List = CSLFindString( papszTokens,
"Integer64List" ) >= 0;
2053 supportRealList = CSLFindString( papszTokens,
"RealList" ) >= 0;
2054 supportsStringList = CSLFindString( papszTokens,
"StringList" ) >= 0;
2055 CSLDestroy( papszTokens );
2060#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
2061 if ( driverName == QLatin1String(
"ESRI Shapefile" ) )
2063 supportsDateTime =
false;
2077 if ( supportsDateTime )
2082 if ( supportsBinary )
2087 if ( supportIntegerList )
2092 if ( supportInteger64List )
2097 if ( supportRealList )
2102 if ( supportsStringList )
2108 const char *pszDataSubTypes = GDALGetMetadataItem( driver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
2109 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"Boolean" ) )
2120#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,3,0)
2126 const QString name{ OGR_FldDomain_GetName( domain ) };
2127 const QString description{ OGR_FldDomain_GetDescription( domain ) };
2129 QMetaType::Type fieldType = QMetaType::Type::UnknownType;
2130 QMetaType::Type fieldSubType = QMetaType::Type::UnknownType;
2131 const OGRFieldType domainFieldType = OGR_FldDomain_GetFieldType( domain );
2132 const OGRFieldSubType domainFieldSubType = OGR_FldDomain_GetFieldSubType( domain );
2133 ogrFieldTypeToQVariantType( domainFieldType, domainFieldSubType, fieldType, fieldSubType );
2135 std::unique_ptr< QgsFieldDomain > res;
2136 switch ( OGR_FldDomain_GetDomainType( domain ) )
2140 QList< QgsCodedValue > values;
2141 const OGRCodedValue *codedValue = OGR_CodedFldDomain_GetEnumeration( domain );
2142 while ( codedValue && codedValue->pszCode )
2144 const QString code( codedValue->pszCode );
2149 const QString value( codedValue->pszValue ? codedValue->pszValue : codedValue->pszCode );
2150 values.append(
QgsCodedValue( stringToVariant( domainFieldType, domainFieldSubType, code ), value ) );
2155 res = std::make_unique< QgsCodedFieldDomain >( name, description, fieldType, values );
2162 bool minIsInclusive =
false;
2163 if (
const OGRField *min = OGR_RangeFldDomain_GetMin( domain, &minIsInclusive ) )
2168 bool maxIsInclusive =
false;
2169 if (
const OGRField *max = OGR_RangeFldDomain_GetMax( domain, &maxIsInclusive ) )
2174 res = std::make_unique< QgsRangeFieldDomain >( name, description, fieldType,
2175 minValue, minIsInclusive,
2176 maxValue, maxIsInclusive );
2181 res = std::make_unique< QgsGlobFieldDomain >( name, description, fieldType,
2182 QString( OGR_GlobFldDomain_GetGlob( domain ) ) );
2186 switch ( OGR_FldDomain_GetMergePolicy( domain ) )
2188 case OFDMP_DEFAULT_VALUE:
2194 case OFDMP_GEOMETRY_WEIGHTED:
2199 switch ( OGR_FldDomain_GetSplitPolicy( domain ) )
2201 case OFDSP_DEFAULT_VALUE:
2204 case OFDSP_DUPLICATE:
2207 case OFDSP_GEOMETRY_RATIO:
2219 OGRFieldType domainFieldType = OFTInteger;
2220 OGRFieldSubType domainFieldSubType = OFSTNone;
2221 variantTypeToOgrFieldType( domain->
fieldType(), domainFieldType, domainFieldSubType );
2223 OGRFieldDomainH res =
nullptr;
2224 switch ( domain->
type() )
2228 std::vector< OGRCodedValue > enumeration;
2229 const QList< QgsCodedValue> values = qgis::down_cast< const QgsCodedFieldDomain * >( domain )->values();
2230 enumeration.reserve( values.size() );
2233 OGRCodedValue codedValue;
2234 codedValue.pszCode = CPLStrdup( value.code().toString().toUtf8().constData() );
2235 codedValue.pszValue = CPLStrdup( value.value().toUtf8().constData() );
2236 enumeration.push_back( codedValue );
2239 last.pszCode =
nullptr;
2240 last.pszValue =
nullptr;
2241 enumeration.push_back( last );
2242 res = OGR_CodedFldDomain_Create(
2243 domain->
name().toUtf8().constData(),
2250 for (
const OGRCodedValue &value : std::as_const( enumeration ) )
2252 CPLFree( value.pszCode );
2253 CPLFree( value.pszValue );
2260 std::unique_ptr< OGRField > min = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimum(), domainFieldType );
2261 std::unique_ptr< OGRField > max = variantToOGRField( qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximum(), domainFieldType );
2264 res = OGR_RangeFldDomain_Create(
2265 domain->
name().toUtf8().constData(),
2270 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->minimumIsInclusive(),
2272 qgis::down_cast< const QgsRangeFieldDomain * >( domain )->maximumIsInclusive()
2279 res = OGR_GlobFldDomain_Create(
2280 domain->
name().toUtf8().constData(),
2284 qgis::down_cast< const QgsGlobFieldDomain * >( domain )->glob().toUtf8().constData()
2293 OGR_FldDomain_SetMergePolicy( res, OFDMP_DEFAULT_VALUE );
2296 OGR_FldDomain_SetMergePolicy( res, OFDMP_GEOMETRY_WEIGHTED );
2299 OGR_FldDomain_SetMergePolicy( res, OFDMP_SUM );
2306 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DEFAULT_VALUE );
2309 OGR_FldDomain_SetSplitPolicy( res, OFDSP_GEOMETRY_RATIO );
2312 OGR_FldDomain_SetSplitPolicy( res, OFDSP_DUPLICATE );
2325#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
2329 const QVariantMap datasetUriParts = ogrProviderMetadata->
decodeUri( datasetUri );
2331 const QString leftTableName( GDALRelationshipGetLeftTableName( relationship ) );
2333 QVariantMap leftTableUriParts = datasetUriParts;
2334 leftTableUriParts.insert( QStringLiteral(
"layerName" ), leftTableName );
2335 const QString leftTableSource = ogrProviderMetadata->
encodeUri( leftTableUriParts );
2337 const QString rightTableName( GDALRelationshipGetRightTableName( relationship ) );
2338 QVariantMap rightTableUriParts = datasetUriParts;
2339 rightTableUriParts.insert( QStringLiteral(
"layerName" ), rightTableName );
2340 const QString rightTableSource = ogrProviderMetadata->
encodeUri( rightTableUriParts );
2342 const QString mappingTableName( GDALRelationshipGetMappingTableName( relationship ) );
2343 QString mappingTableSource;
2344 if ( !mappingTableName.isEmpty() )
2346 QVariantMap mappingTableUriParts = datasetUriParts;
2347 mappingTableUriParts.insert( QStringLiteral(
"layerName" ), mappingTableName );
2348 mappingTableSource = ogrProviderMetadata->
encodeUri( mappingTableUriParts );
2351 const QString relationshipName( GDALRelationshipGetName( relationship ) );
2353 char **cslLeftTableFieldNames = GDALRelationshipGetLeftTableFields( relationship );
2355 CSLDestroy( cslLeftTableFieldNames );
2357 char **cslRightTableFieldNames = GDALRelationshipGetRightTableFields( relationship );
2359 CSLDestroy( cslRightTableFieldNames );
2361 char **cslLeftMappingTableFieldNames = GDALRelationshipGetLeftMappingTableFields( relationship );
2363 CSLDestroy( cslLeftMappingTableFieldNames );
2365 char **cslRightMappingTableFieldNames = GDALRelationshipGetRightMappingTableFields( relationship );
2367 CSLDestroy( cslRightMappingTableFieldNames );
2369 const QString forwardPathLabel( GDALRelationshipGetForwardPathLabel( relationship ) );
2370 const QString backwardPathLabel( GDALRelationshipGetBackwardPathLabel( relationship ) );
2371 const QString relatedTableType( GDALRelationshipGetRelatedTableType( relationship ) );
2373 const GDALRelationshipType relationshipType = GDALRelationshipGetType( relationship );
2375 switch ( relationshipType )
2381 case GRT_ASSOCIATION:
2385 case GRT_AGGREGATION:
2386 QgsLogger::warning(
"Aggregation relationships are not supported, treating as association instead" );
2390 const GDALRelationshipCardinality eCardinality = GDALRelationshipGetCardinality( relationship );
2392 switch ( eCardinality )
2394 case GRC_ONE_TO_ONE:
2397 case GRC_ONE_TO_MANY:
2400 case GRC_MANY_TO_ONE:
2403 case GRC_MANY_TO_MANY:
2408 switch ( cardinality )
2417 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2418 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2433 QString(), QString(), rightTableSource, QStringLiteral(
"ogr" ),
2434 QString(), QString(), leftTableSource, QStringLiteral(
"ogr" ) );
2452 GDALRelationshipCardinality gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2456 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_ONE;
2459 gCardinality = GDALRelationshipCardinality::GRC_ONE_TO_MANY;
2462 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_ONE;
2465 gCardinality = GDALRelationshipCardinality::GRC_MANY_TO_MANY;
2472 const QString leftTableName = leftParts.value( QStringLiteral(
"layerName" ) ).toString();
2473 if ( leftTableName.isEmpty() )
2475 error = QObject::tr(
"Parent table name was not set" );
2480 const QString rightTableName = rightParts.value( QStringLiteral(
"layerName" ) ).toString();
2481 if ( rightTableName.isEmpty() )
2483 error = QObject::tr(
"Child table name was not set" );
2487 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != rightParts.value( QStringLiteral(
"path" ) ).toString() )
2489 error = QObject::tr(
"Parent and child table must be from the same dataset" );
2493 QString mappingTableName;
2497 mappingTableName = mappingParts.value( QStringLiteral(
"layerName" ) ).toString();
2498 if ( leftParts.value( QStringLiteral(
"path" ) ).toString() != mappingParts.value( QStringLiteral(
"path" ) ).toString() )
2500 error = QObject::tr(
"Parent and mapping table must be from the same dataset" );
2506 leftTableName.toLocal8Bit().constData(),
2507 rightTableName.toLocal8Bit().constData(),
2512 int count = leftFieldNames.count();
2513 char **lst =
new char *[count + 1];
2517 for (
const QString &
string : leftFieldNames )
2519 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2523 lst[count] =
nullptr;
2524 GDALRelationshipSetLeftTableFields( relationH.get(), lst );
2529 count = rightFieldNames.count();
2530 lst =
new char *[count + 1];
2534 for (
const QString &
string : rightFieldNames )
2536 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2540 lst[count] =
nullptr;
2541 GDALRelationshipSetRightTableFields( relationH.get(), lst );
2544 if ( !mappingTableName.isEmpty() )
2546 GDALRelationshipSetMappingTableName( relationH.get(), mappingTableName.toLocal8Bit().constData() );
2550 int count = leftFieldNames.count();
2551 char **lst =
new char *[count + 1];
2555 for (
const QString &
string : leftFieldNames )
2557 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2561 lst[count] =
nullptr;
2562 GDALRelationshipSetLeftMappingTableFields( relationH.get(), lst );
2567 count = rightFieldNames.count();
2568 lst =
new char *[count + 1];
2572 for (
const QString &
string : rightFieldNames )
2574 lst[pos] = CPLStrdup(
string.toLocal8Bit().constData() );
2578 lst[count] =
nullptr;
2579 GDALRelationshipSetRightMappingTableFields( relationH.get(), lst );
2587 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_ASSOCIATION );
2591 GDALRelationshipSetType( relationH.get(), GDALRelationshipType::GRT_COMPOSITE );
2597 GDALRelationshipSetForwardPathLabel( relationH.get(), relationship.
forwardPathLabel().toLocal8Bit().constData() );
2599 GDALRelationshipSetBackwardPathLabel( relationH.get(), relationship.
backwardPathLabel().toLocal8Bit().constData() );
2603 GDALRelationshipSetRelatedTableType( relationH.get(), relationship.
relatedTableType().toLocal8Bit().constData() );
2611 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2615 errCause = QObject::tr(
"No styles available on DB" );
2619 if ( OGR_L_GetFeatureCount( hLayer, TRUE ) == 0 )
2622 errCause = QObject::tr(
"No styles available on DB" );
2626 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2628 OGR_L_ResetReading( hLayer );
2630 QList<qlonglong> listTimestamp;
2631 QMap<int, QString> mapIdToStyleName;
2632 QMap<int, QString> mapIdToDescription;
2633 QMap<qlonglong, QList<int> > mapTimestampToId;
2634 int numberOfRelatedStyles = 0;
2642 QString tableName( QString::fromUtf8(
2643 OGR_F_GetFieldAsString( hFeature.get(),
2644 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ) ) ) );
2645 QString geometryColumn( QString::fromUtf8(
2646 OGR_F_GetFieldAsString( hFeature.get(),
2647 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ) ) ) );
2648 QString styleName( QString::fromUtf8(
2649 OGR_F_GetFieldAsString( hFeature.get(),
2650 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) ) );
2651 QString description( QString::fromUtf8(
2652 OGR_F_GetFieldAsString( hFeature.get(),
2653 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ) ) ) );
2654 int fid =
static_cast<int>( OGR_F_GetFID( hFeature.get() ) );
2655 if ( tableName == layerName &&
2656 geometryColumn == geomColumn )
2659 QString id( QString::number( fid ) );
2661 names.append( styleName );
2662 descriptions.append( description );
2663 ++ numberOfRelatedStyles;
2667 int year, month, day, hour, minute, second, TZ;
2668 OGR_F_GetFieldAsDateTime( hFeature.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2669 &year, &month, &day, &hour, &minute, &second, &TZ );
2670 const qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2671 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2673 listTimestamp.append( ts );
2674 mapIdToStyleName[fid] = styleName;
2675 mapIdToDescription[fid] = description;
2676 mapTimestampToId[ts].append( fid );
2680 std::sort( listTimestamp.begin(), listTimestamp.end() );
2682 for (
int i = listTimestamp.size() - 1; i >= 0; i-- )
2684 const QList<int> &listId = mapTimestampToId[listTimestamp[i]];
2685 for (
int j = 0; j < listId.size(); j++ )
2687 int fid = listId[j];
2688 QString id( QString::number( fid ) );
2690 names.append( mapIdToStyleName[fid] );
2691 descriptions.append( mapIdToDescription[fid] );
2695 return numberOfRelatedStyles;
2703 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2707 const QString realStyleId = styleId.isEmpty() ? layerName : styleId;
2709 const QString checkQuery = QStringLiteral(
"f_table_schema=''"
2710 " AND f_table_name=%1"
2711 " AND f_geometry_column=%2"
2712 " AND styleName=%3" )
2713 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2714 QgsOgrProviderUtils::quotedValue( geomColumn ),
2715 QgsOgrProviderUtils::quotedValue( realStyleId ) );
2716 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2717 OGR_L_ResetReading( hLayer );
2719 OGR_L_ResetReading( hLayer );
2729 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2733 errCause = QObject::tr(
"No styles available on DB" );
2738 int id = styleId.toInt( &ok );
2741 errCause = QObject::tr(
"Invalid style identifier" );
2748 errCause = QObject::tr(
"No style corresponding to style identifier" );
2752 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2753 QString styleQML( QString::fromUtf8(
2754 OGR_F_GetFieldAsString( hFeature.get(),
2755 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) ) );
2756 OGR_L_ResetReading( hLayer );
2765 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2770 errCause = QObject::tr(
"Connection to database failed" );
2775 if ( OGR_L_DeleteFeature( hLayer, styleId.toInt() ) != OGRERR_NONE )
2777 errCause = QObject::tr(
"Error executing the delete query." );
2790 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2794 errCause = QObject::tr(
"No styles available on DB" );
2798 QString selectQmlQuery = QStringLiteral(
"f_table_schema=''"
2799 " AND f_table_name=%1"
2800 " AND f_geometry_column=%2"
2801 " ORDER BY CASE WHEN useAsDefault THEN 1 ELSE 2 END"
2802 ",update_time DESC" )
2803 .arg( QgsOgrProviderUtils::quotedValue( layerName ),
2804 QgsOgrProviderUtils::quotedValue( geomColumn ) );
2805 OGR_L_SetAttributeFilter( hLayer, selectQmlQuery.toUtf8().constData() );
2806 OGR_L_ResetReading( hLayer );
2807 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2809 qlonglong moreRecentTimestamp = 0;
2815 if ( OGR_F_GetFieldAsInteger( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ) ) )
2817 styleQML = QString::fromUtf8(
2818 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2819 styleName = QString::fromUtf8(
2820 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2824 int year, month, day, hour, minute, second, TZ;
2825 OGR_F_GetFieldAsDateTime( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"update_time" ),
2826 &year, &month, &day, &hour, &minute, &second, &TZ );
2827 qlonglong ts = second + minute * 60 + hour * 3600 + day * 24 * 3600 +
2828 static_cast<qlonglong
>( month ) * 31 * 24 * 3600 +
static_cast<qlonglong
>( year ) * 12 * 31 * 24 * 3600;
2829 if ( ts > moreRecentTimestamp )
2831 moreRecentTimestamp = ts;
2832 styleQML = QString::fromUtf8(
2833 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ) ) );
2834 styleName = QString::fromUtf8(
2835 OGR_F_GetFieldAsString( hFeat.get(), OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ) ) );
2838 OGR_L_ResetReading( hLayer );
2844 GDALDatasetH hDS,
const QString &layerName,
const QString &geomColumn,
const QString &qmlStyle,
const QString &sldStyle,
2845 const QString &styleName,
const QString &styleDescription,
2846 const QString &uiFileContent,
bool useAsDefault, QString &errCause
2850 OGRLayerH hLayer = GDALDatasetGetLayerByName( hDS,
"layer_styles" );
2857 char **options =
nullptr;
2859 options = CSLSetNameValue( options,
"FID",
"id" );
2860 hLayer = GDALDatasetCreateLayer( hDS,
"layer_styles",
nullptr, wkbNone, options );
2861 QgsOgrProviderUtils::invalidateCachedDatasets( QString::fromUtf8( GDALGetDescription( hDS ) ) );
2862 CSLDestroy( options );
2865 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2871 OGR_Fld_SetWidth( fld.get(), 256 );
2872 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2876 OGR_Fld_SetWidth( fld.get(), 256 );
2877 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2881 OGR_Fld_SetWidth( fld.get(), 256 );
2882 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2886 OGR_Fld_SetWidth( fld.get(), 256 );
2887 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2891 OGR_Fld_SetWidth( fld.get(), 30 );
2892 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2896 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2900 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2904 OGR_Fld_SetSubType( fld.get(), OFSTBoolean );
2905 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2909 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2913 OGR_Fld_SetWidth( fld.get(), 30 );
2914 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2918 OGR_Fld_SetWidth( fld.get(), 30 );
2919 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2923 OGR_Fld_SetDefault( fld.get(),
"CURRENT_TIMESTAMP" );
2924 ok &= OGR_L_CreateField( hLayer, fld.get(),
true ) == OGRERR_NONE;
2928 errCause = QObject::tr(
"Unable to save layer style. It's not possible to create the destination table on the database." );
2933 QString realStyleName =
2934 styleName.isEmpty() ? layerName : styleName;
2936 OGRFeatureDefnH hLayerDefn = OGR_L_GetLayerDefn( hLayer );
2940 QString oldDefaultQuery = QStringLiteral(
"useAsDefault = 1 AND f_table_schema=''"
2941 " AND f_table_name=%1"
2942 " AND f_geometry_column=%2" )
2943 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
2944 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) );
2945 OGR_L_SetAttributeFilter( hLayer, oldDefaultQuery.toUtf8().constData() );
2949 OGR_F_SetFieldInteger( hFeature.get(),
2950 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
2952 bool ok = OGR_L_SetFeature( hLayer, hFeature.get() ) == 0;
2955 QgsDebugError( QStringLiteral(
"Could not unset previous useAsDefault style" ) );
2960 QString checkQuery = QStringLiteral(
"f_table_schema=''"
2961 " AND f_table_name=%1"
2962 " AND f_geometry_column=%2"
2963 " AND styleName=%3" )
2964 .arg( QgsOgrProviderUtils::quotedValue( layerName ) )
2965 .arg( QgsOgrProviderUtils::quotedValue( geomColumn ) )
2966 .arg( QgsOgrProviderUtils::quotedValue( realStyleName ) );
2967 OGR_L_SetAttributeFilter( hLayer, checkQuery.toUtf8().constData() );
2968 OGR_L_ResetReading( hLayer );
2970 OGR_L_ResetReading( hLayer );
2979 hFeature.reset( OGR_F_Create( hLayerDefn ) );
2980 OGR_F_SetFieldString( hFeature.get(),
2981 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_catalog" ),
2983 OGR_F_SetFieldString( hFeature.get(),
2984 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_schema" ),
2986 OGR_F_SetFieldString( hFeature.get(),
2987 OGR_FD_GetFieldIndex( hLayerDefn,
"f_table_name" ),
2988 layerName.toUtf8().constData() );
2989 OGR_F_SetFieldString( hFeature.get(),
2990 OGR_FD_GetFieldIndex( hLayerDefn,
"f_geometry_column" ),
2991 geomColumn.toUtf8().constData() );
2992 OGR_F_SetFieldString( hFeature.get(),
2993 OGR_FD_GetFieldIndex( hLayerDefn,
"styleName" ),
2994 realStyleName.toUtf8().constData() );
2995 if ( !uiFileContent.isEmpty() )
2997 OGR_F_SetFieldString( hFeature.get(),
2998 OGR_FD_GetFieldIndex( hLayerDefn,
"ui" ),
2999 uiFileContent.toUtf8().constData() );
3002 OGR_F_SetFieldString( hFeature.get(),
3003 OGR_FD_GetFieldIndex( hLayerDefn,
"styleQML" ),
3004 qmlStyle.toUtf8().constData() );
3005 OGR_F_SetFieldString( hFeature.get(),
3006 OGR_FD_GetFieldIndex( hLayerDefn,
"styleSLD" ),
3007 sldStyle.toUtf8().constData() );
3008 OGR_F_SetFieldInteger( hFeature.get(),
3009 OGR_FD_GetFieldIndex( hLayerDefn,
"useAsDefault" ),
3010 useAsDefault ? 1 : 0 );
3011 OGR_F_SetFieldString( hFeature.get(),
3012 OGR_FD_GetFieldIndex( hLayerDefn,
"description" ),
3013 ( styleDescription.isEmpty() ? QDateTime::currentDateTime().toString() : styleDescription ).toUtf8().constData() );
3014 OGR_F_SetFieldString( hFeature.get(),
3015 OGR_FD_GetFieldIndex( hLayerDefn,
"owner" ),
3020 bFeatureOK = OGR_L_CreateFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3022 bFeatureOK = OGR_L_SetFeature( hLayer, hFeature.get() ) == OGRERR_NONE;
3027 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.
@ PolyhedralSurfaceM
PolyhedralSurfaceM.
@ MultiLineStringZM
MultiLineStringZM.
@ MultiPointZM
MultiPointZM.
@ MultiPointZ
MultiPointZ.
@ CompoundCurve
CompoundCurve.
@ MultiPolygonZM
MultiPolygonZM.
@ LineStringM
LineStringM.
@ MultiLineStringM
MultiLineStringM.
@ MultiPointM
MultiPointM.
@ LineStringZM
LineStringZM.
@ GeometryCollectionZM
GeometryCollectionZM.
@ CompoundCurveZM
CompoundCurveZM.
@ CompoundCurveM
CompoundCurveM.
@ MultiPolygon
MultiPolygon.
@ GeometryCollectionZ
GeometryCollectionZ.
@ GeometryCollectionM
GeometryCollectionM.
@ CircularStringZM
CircularStringZM.
@ MultiSurfaceZ
MultiSurfaceZ.
@ CurvePolygonZM
CurvePolygonZM.
@ MultiLineString
MultiLineString.
@ MultiPolygonM
MultiPolygonM.
@ MultiCurveZM
MultiCurveZM.
@ MultiSurfaceZM
MultiSurfaceZM.
@ CurvePolygonM
CurvePolygonM.
@ CircularString
CircularString.
@ MultiLineStringZ
MultiLineStringZ.
@ GeometryCollection
GeometryCollection.
@ PolyhedralSurfaceZM
PolyhedralSurfaceM.
@ MultiPolygonZ
MultiPolygonZ.
@ CurvePolygonZ
CurvePolygonZ.
@ CompoundCurveZ
CompoundCurveZ.
@ MultiCurveZ
MultiCurveZ.
@ MultiCurveM
MultiCurveM.
@ PolyhedralSurfaceZ
PolyhedralSurfaceZ.
@ CircularStringM
CircularStringM.
@ CurvePolygon
CurvePolygon.
@ CircularStringZ
CircularStringZ.
@ LineStringZ
LineStringZ.
@ PolyhedralSurface
PolyhedralSurface.
@ MultiSurface
MultiSurface.
@ PreferredGdal
Preferred format for conversion of CRS to WKT for use with the GDAL library.
static QgsFontManager * fontManager()
Returns the application font manager, which manages available fonts and font installation for the QGI...
static endian_t endian()
Returns whether this machine uses big or little endian.
Associates a code and a value.
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).
Abstract base class for fill symbol layers.
QString processFontFamilyName(const QString &name) const
Processes a font family name, applying any matching fontFamilyReplacements() to the name.
static bool fontFamilyMatchOnSystem(const QString &family, QString *chosen=nullptr, bool *match=nullptr)
Check whether font family is on system.
A geometry is the spatial representation of a feature.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
Abstract base class for line symbol layers.
static void warning(const QString &msg)
Goes to qWarning.
Context for a MapInfo symbol conversion operation.
static QgsFillSymbol * convertFillSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, const QColor &backColor=QColor())
Converts the MapInfo fill symbol with the specified identifier to a QgsFillSymbol.
static QgsMarkerSymbol * convertMarkerSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &color, double size, Qgis::RenderUnit sizeUnit)
Converts the MapInfo marker symbol with the specified identifier to a QgsMarkerSymbol.
static QgsLineSymbol * convertLineSymbol(int identifier, QgsMapInfoSymbolConversionContext &context, const QColor &foreColor, double size, Qgis::RenderUnit sizeUnit, bool interleaved=false)
Converts the MapInfo line symbol with the specified identifier to a QgsLineSymbol.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
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 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.