QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgsjsonutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsjsonutils.h
3 -------------
4 Date : May 206
5 Copyright : (C) 2016 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsjsonutils.h"
17#include "qgsfeatureiterator.h"
18#include "qgsogrutils.h"
19#include "qgsgeometry.h"
20#include "qgsvectorlayer.h"
21#include "qgsrelation.h"
22#include "qgsrelationmanager.h"
23#include "qgsproject.h"
24#include "qgsexception.h"
25#include "qgslogger.h"
27#include "qgsfieldformatter.h"
28#include "qgsapplication.h"
29#include "qgsfeatureid.h"
30
31#include <QJsonDocument>
32#include <QJsonArray>
33#include <QTextCodec>
34#include <nlohmann/json.hpp>
35
37 : mPrecision( precision )
38 , mLayer( vectorLayer )
39{
40 if ( vectorLayer )
41 {
42 mCrs = vectorLayer->crs();
43 mTransform.setSourceCrs( mCrs );
44 }
45
46 // Default 4326
47 mDestinationCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) );
48 mTransform.setDestinationCrs( mDestinationCrs );
49}
50
52{
53 mLayer = vectorLayer;
54 if ( vectorLayer )
55 {
56 mCrs = vectorLayer->crs();
57 mTransform.setSourceCrs( mCrs );
58 }
59}
60
62{
63 return mLayer.data();
64}
65
67{
68 mCrs = crs;
69 mTransform.setSourceCrs( mCrs );
70}
71
73{
74 return mCrs;
75}
76
77QString QgsJsonExporter::exportFeature( const QgsFeature &feature, const QVariantMap &extraProperties,
78 const QVariant &id, int indent ) const
79{
80 return QString::fromStdString( exportFeatureToJsonObject( feature, extraProperties, id ).dump( indent ) );
81}
82
83json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, const QVariantMap &extraProperties, const QVariant &id ) const
84{
85 json featureJson
86 {
87 { "type", "Feature" },
88 };
89 if ( id.isValid() )
90 {
91 bool ok = false;
92 auto intId = id.toLongLong( &ok );
93 if ( ok )
94 {
95 featureJson["id"] = intId;
96 }
97 else
98 {
99 featureJson["id"] = id.toString().toStdString();
100 }
101 }
102 else if ( FID_IS_NULL( feature.id() ) )
103 {
104 featureJson["id"] = nullptr;
105 }
106 else
107 {
108 featureJson["id"] = feature.id();
109 }
110
111 QgsGeometry geom = feature.geometry();
112 if ( !geom.isNull() && mIncludeGeometry )
113 {
114 if ( mCrs.isValid() )
115 {
116 try
117 {
118 QgsGeometry transformed = geom;
119 if ( mTransformGeometries && transformed.transform( mTransform ) == Qgis::GeometryOperationResult::Success )
120 geom = transformed;
121 }
122 catch ( QgsCsException &cse )
123 {
124 Q_UNUSED( cse )
125 }
126 }
127 QgsRectangle box = geom.boundingBox();
128
130 {
131 featureJson[ "bbox" ] =
132 {
133 qgsRound( box.xMinimum(), mPrecision ),
134 qgsRound( box.yMinimum(), mPrecision ),
135 qgsRound( box.xMaximum(), mPrecision ),
136 qgsRound( box.yMaximum(), mPrecision )
137 };
138 }
139 featureJson[ "geometry" ] = geom.asJsonObject( mPrecision );
140 }
141 else
142 {
143 featureJson[ "geometry" ] = nullptr;
144 }
145
146 // build up properties element
147 int attributeCounter { 0 };
148 json properties;
149 if ( mIncludeAttributes || !extraProperties.isEmpty() )
150 {
151 //read all attribute values from the feature
152 if ( mIncludeAttributes )
153 {
154 QgsFields fields = mLayer ? mLayer->fields() : feature.fields();
155 // List of formatters through we want to pass the values
156 QStringList formattersAllowList;
157 formattersAllowList << QStringLiteral( "KeyValue" )
158 << QStringLiteral( "List" )
159 << QStringLiteral( "ValueRelation" )
160 << QStringLiteral( "ValueMap" );
161
162 for ( int i = 0; i < fields.count(); ++i )
163 {
164 if ( ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
165 continue;
166
167 QVariant val = feature.attributes().at( i );
168
169 if ( mLayer )
170 {
171 const QgsEditorWidgetSetup setup = fields.at( i ).editorWidgetSetup();
173 if ( formattersAllowList.contains( fieldFormatter->id() ) )
174 val = fieldFormatter->representValue( mLayer.data(), i, setup.config(), QVariant(), val );
175 }
176
177 QString name = fields.at( i ).name();
178 if ( mAttributeDisplayName )
179 {
180 name = mLayer->attributeDisplayName( i );
181 }
182 properties[ name.toStdString() ] = QgsJsonUtils::jsonFromVariant( val );
183 attributeCounter++;
184 }
185 }
186
187 if ( !extraProperties.isEmpty() )
188 {
189 QVariantMap::const_iterator it = extraProperties.constBegin();
190 for ( ; it != extraProperties.constEnd(); ++it )
191 {
192 properties[ it.key().toStdString() ] = QgsJsonUtils::jsonFromVariant( it.value() );
193 attributeCounter++;
194 }
195 }
196
197 // related attributes
198 if ( mLayer && mIncludeRelatedAttributes )
199 {
200 QList< QgsRelation > relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer.data() );
201 for ( const auto &relation : std::as_const( relations ) )
202 {
203 QgsFeatureRequest req = relation.getRelatedFeaturesRequest( feature );
205 QgsVectorLayer *childLayer = relation.referencingLayer();
206 json relatedFeatureAttributes;
207 if ( childLayer )
208 {
209 QgsFeatureIterator it = childLayer->getFeatures( req );
210 QVector<QVariant> attributeWidgetCaches;
211 int fieldIndex = 0;
212 const QgsFields fields { childLayer->fields() };
213 for ( const QgsField &field : fields )
214 {
217 attributeWidgetCaches.append( fieldFormatter->createCache( childLayer, fieldIndex, setup.config() ) );
218 fieldIndex++;
219 }
220 QgsFeature relatedFet;
221 while ( it.nextFeature( relatedFet ) )
222 {
223 relatedFeatureAttributes += QgsJsonUtils::exportAttributesToJsonObject( relatedFet, childLayer, attributeWidgetCaches );
224 }
225 }
226 properties[ relation.name().toStdString() ] = relatedFeatureAttributes;
227 attributeCounter++;
228 }
229 }
230 }
231 featureJson[ "properties" ] = properties;
232 return featureJson;
233}
234
235QString QgsJsonExporter::exportFeatures( const QgsFeatureList &features, int indent ) const
236{
237 return QString::fromStdString( exportFeaturesToJsonObject( features ).dump( indent ) );
238}
239
241{
242 json data
243 {
244 { "type", "FeatureCollection" },
245 { "features", json::array() }
246 };
247 for ( const QgsFeature &feature : std::as_const( features ) )
248 {
249 data["features"].push_back( exportFeatureToJsonObject( feature ) );
250 }
251 return data;
252}
253
255{
256 mDestinationCrs = destinationCrs;
257 mTransform.setDestinationCrs( mDestinationCrs );
258}
259
260//
261// QgsJsonUtils
262//
263
264QgsFeatureList QgsJsonUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
265{
266 if ( !encoding )
267 encoding = QTextCodec::codecForName( "UTF-8" );
268
269 return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
270}
271
272QgsFields QgsJsonUtils::stringToFields( const QString &string, QTextCodec *encoding )
273{
274 if ( !encoding )
275 encoding = QTextCodec::codecForName( "UTF-8" );
276
277 return QgsOgrUtils::stringToFields( string, encoding );
278}
279
280QString QgsJsonUtils::encodeValue( const QVariant &value )
281{
282 if ( QgsVariantUtils::isNull( value ) )
283 return QStringLiteral( "null" );
284
285 switch ( value.type() )
286 {
287 case QVariant::Int:
288 case QVariant::UInt:
289 case QVariant::LongLong:
290 case QVariant::ULongLong:
291 case QVariant::Double:
292 return value.toString();
293
294 case QVariant::Bool:
295 return value.toBool() ? "true" : "false";
296
297 case QVariant::StringList:
298 case QVariant::List:
299 case QVariant::Map:
300 return QString::fromUtf8( QJsonDocument::fromVariant( value ).toJson( QJsonDocument::Compact ) );
301
302 default:
303 case QVariant::String:
304 QString v = value.toString()
305 .replace( '\\', QLatin1String( "\\\\" ) )
306 .replace( '"', QLatin1String( "\\\"" ) )
307 .replace( '\r', QLatin1String( "\\r" ) )
308 .replace( '\b', QLatin1String( "\\b" ) )
309 .replace( '\t', QLatin1String( "\\t" ) )
310 .replace( '/', QLatin1String( "\\/" ) )
311 .replace( '\n', QLatin1String( "\\n" ) );
312
313 return v.prepend( '"' ).append( '"' );
314 }
315}
316
317QString QgsJsonUtils::exportAttributes( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
318{
319 QgsFields fields = feature.fields();
320 QString attrs;
321 for ( int i = 0; i < fields.count(); ++i )
322 {
323 if ( i > 0 )
324 attrs += QLatin1String( ",\n" );
325
326 QVariant val = feature.attributes().at( i );
327
328 if ( layer )
329 {
330 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
332 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
333 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
334 }
335
336 attrs += encodeValue( fields.at( i ).name() ) + ':' + encodeValue( val );
337 }
338 return attrs.prepend( '{' ).append( '}' );
339}
340
341QVariantList QgsJsonUtils::parseArray( const QString &json, QVariant::Type type )
342{
343 QString errorMessage;
344 QVariantList result;
345 try
346 {
347 const auto jObj( json::parse( json.toStdString() ) );
348 if ( ! jObj.is_array() )
349 {
350 throw json::parse_error::create( 0, 0, QStringLiteral( "JSON value must be an array" ).toStdString() );
351 }
352 for ( const auto &item : jObj )
353 {
354 // Create a QVariant from the array item
355 QVariant v;
356 if ( item.is_number_integer() )
357 {
358 v = item.get<int>();
359 }
360 else if ( item.is_number_unsigned() )
361 {
362 v = item.get<unsigned>();
363 }
364 else if ( item.is_number_float() )
365 {
366 // Note: it's a double and not a float on purpose
367 v = item.get<double>();
368 }
369 else if ( item.is_string() )
370 {
371 v = QString::fromStdString( item.get<std::string>() );
372 }
373 else if ( item.is_boolean() )
374 {
375 v = item.get<bool>();
376 }
377 else if ( item.is_null() )
378 {
379 // Fallback to int
380 v = QVariant( type == QVariant::Type::Invalid ? QVariant::Type::Int : type );
381 }
382
383 // If a destination type was specified (it's not invalid), try to convert
384 if ( type != QVariant::Invalid )
385 {
386 if ( ! v.convert( static_cast<int>( type ) ) )
387 {
388 QgsLogger::warning( QStringLiteral( "Cannot convert json array element to specified type, ignoring: %1" ).arg( v.toString() ) );
389 }
390 else
391 {
392 result.push_back( v );
393 }
394 }
395 else
396 {
397 result.push_back( v );
398 }
399 }
400 }
401 catch ( json::parse_error &ex )
402 {
403 errorMessage = ex.what();
404 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( ex.what(), json ) );
405 }
406
407 return result;
408}
409
410json QgsJsonUtils::jsonFromVariant( const QVariant &val )
411{
412 if ( QgsVariantUtils::isNull( val ) )
413 {
414 return nullptr;
415 }
416 json j;
417 if ( val.type() == QVariant::Type::Map )
418 {
419 const QVariantMap &vMap = val.toMap();
420 json jMap = json::object();
421 for ( auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
422 {
423 jMap[ it.key().toStdString() ] = jsonFromVariant( it.value() );
424 }
425 j = jMap;
426 }
427 else if ( val.type() == QVariant::Type::List || val.type() == QVariant::Type::StringList )
428 {
429 const QVariantList &vList = val.toList();
430 json jList = json::array();
431 for ( const auto &v : vList )
432 {
433 jList.push_back( jsonFromVariant( v ) );
434 }
435 j = jList;
436 }
437 else
438 {
439 switch ( val.userType() )
440 {
441 case QMetaType::Int:
442 case QMetaType::UInt:
443 case QMetaType::LongLong:
444 case QMetaType::ULongLong:
445 j = val.toLongLong();
446 break;
447 case QMetaType::Double:
448 case QMetaType::Float:
449 j = val.toDouble();
450 break;
451 case QMetaType::Bool:
452 j = val.toBool();
453 break;
454 case QMetaType::QByteArray:
455 j = val.toByteArray().toBase64().toStdString();
456 break;
457 default:
458 j = val.toString().toStdString();
459 break;
460 }
461 }
462 return j;
463}
464
465QVariant QgsJsonUtils::parseJson( const std::string &jsonString )
466{
467 QString error;
468 const QVariant res = parseJson( jsonString, error );
469
470 if ( !error.isEmpty() )
471 {
472 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( error,
473 QString::fromStdString( jsonString ) ) );
474 }
475 return res;
476}
477
478QVariant QgsJsonUtils::parseJson( const std::string &jsonString, QString &error )
479{
480 // tracks whether entire json string is a primitive
481 bool isPrimitive = true;
482
483 std::function<QVariant( json )> _parser { [ & ]( json jObj ) -> QVariant {
484 QVariant result;
485 if ( jObj.is_array() )
486 {
487 isPrimitive = false;
488 QVariantList results;
489 results.reserve( jObj.size() );
490 for ( const auto &item : jObj )
491 {
492 results.push_back( _parser( item ) );
493 }
494 result = results;
495 }
496 else if ( jObj.is_object() )
497 {
498 isPrimitive = false;
499 QVariantMap results;
500 for ( const auto &item : jObj.items() )
501 {
502 const auto key { QString::fromStdString( item.key() ) };
503 const auto value { _parser( item.value() ) };
504 results[ key ] = value;
505 }
506 result = results;
507 }
508 else
509 {
510 if ( jObj.is_number_integer() )
511 {
512 result = jObj.get<int>();
513 }
514 else if ( jObj.is_number_unsigned() )
515 {
516 result = jObj.get<unsigned>();
517 }
518 else if ( jObj.is_boolean() )
519 {
520 result = jObj.get<bool>();
521 }
522 else if ( jObj.is_number_float() )
523 {
524 // Note: it's a double and not a float on purpose
525 result = jObj.get<double>();
526 }
527 else if ( jObj.is_string() )
528 {
529 if ( isPrimitive && jObj.get<std::string>().length() == 0 )
530 {
531 result = QString::fromStdString( jObj.get<std::string>() ).append( "\"" ).insert( 0, "\"" );
532 }
533 else
534 {
535 result = QString::fromStdString( jObj.get<std::string>() );
536 }
537 }
538 else if ( jObj.is_null() )
539 {
540 // Do nothing (leave invalid)
541 }
542 }
543 return result;
544 }
545 };
546
547 error.clear();
548 try
549 {
550 const json j = json::parse( jsonString );
551 return _parser( j );
552 }
553 catch ( json::parse_error &ex )
554 {
555 error = QString::fromStdString( ex.what() );
556 }
557 return QVariant();
558}
559
560QVariant QgsJsonUtils::parseJson( const QString &jsonString )
561{
562 return parseJson( jsonString.toStdString() );
563}
564
565json QgsJsonUtils::exportAttributesToJsonObject( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
566{
567 QgsFields fields = feature.fields();
568 json attrs;
569 for ( int i = 0; i < fields.count(); ++i )
570 {
571 QVariant val = feature.attributes().at( i );
572
573 if ( layer )
574 {
575 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
577 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
578 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
579 }
580 attrs[fields.at( i ).name().toStdString()] = jsonFromVariant( val );
581 }
582 return attrs;
583}
@ Success
Operation succeeded.
static QgsFieldFormatterRegistry * fieldFormatterRegistry()
Gets the registry of available field formatters.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source coordinate reference system.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination coordinate reference system.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Holder for the widget type and its configuration for a field.
QVariantMap config() const
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
QgsGeometry geometry
Definition: qgsfeature.h:67
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
QgsFieldFormatter * fieldFormatter(const QString &id) const
Gets a field formatter by its id.
A field formatter helps to handle and display values for a field.
virtual QVariant createCache(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config) const
Create a cache for a given field.
virtual QString id() const =0
Returns a unique id for this field formatter.
virtual QString representValue(QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value) const
Create a pretty String representation of the value.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:52
QString name
Definition: qgsfield.h:61
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:672
Container of fields for a vector layer.
Definition: qgsfields.h:45
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Q_GADGET bool isNull
Definition: qgsgeometry.h:166
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
virtual json asJsonObject(int precision=17) const
Exports the geometry to a json object.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
json exportFeatureToJsonObject(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant()) const
Returns a QJsonObject representation of a feature.
json exportFeaturesToJsonObject(const QgsFeatureList &features) const
Returns a JSON object representation of a list of features (feature collection).
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source CRS for feature geometries.
void setDestinationCrs(const QgsCoordinateReferenceSystem &destinationCrs)
Set the destination CRS for feature geometry transformation to destinationCrs, this defaults to EPSG:...
QgsVectorLayer * vectorLayer() const
Returns the associated vector layer, if set.
QString exportFeature(const QgsFeature &feature, const QVariantMap &extraProperties=QVariantMap(), const QVariant &id=QVariant(), int indent=-1) const
Returns a GeoJSON string representation of a feature.
QString exportFeatures(const QgsFeatureList &features, int indent=-1) const
Returns a GeoJSON string representation of a list of features (feature collection).
void setVectorLayer(QgsVectorLayer *vectorLayer)
Sets the associated vector layer (required for related attribute export).
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS for feature geometries.
QgsJsonExporter(QgsVectorLayer *vectorLayer=nullptr, int precision=6)
Constructor for QgsJsonExporter.
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields=QgsFields(), QTextCodec *encoding=nullptr)
Attempts to parse a GeoJSON string to a collection of features.
static QString exportAttributes(const QgsFeature &feature, QgsVectorLayer *layer=nullptr, const QVector< QVariant > &attributeWidgetCaches=QVector< QVariant >())
Exports all attributes from a QgsFeature as a JSON map type.
static Q_INVOKABLE QString encodeValue(const QVariant &value)
Encodes a value to a JSON string representation, adding appropriate quotations and escaping where req...
static QVariant parseJson(const std::string &jsonString)
Converts JSON jsonString to a QVariant, in case of parsing error an invalid QVariant is returned and ...
static json exportAttributesToJsonObject(const QgsFeature &feature, QgsVectorLayer *layer=nullptr, const QVector< QVariant > &attributeWidgetCaches=QVector< QVariant >())
Exports all attributes from a QgsFeature as a json object.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding=nullptr)
Attempts to retrieve the fields from a GeoJSON string representing a collection of features.
static Q_INVOKABLE QVariantList parseArray(const QString &json, QVariant::Type type=QVariant::Invalid)
Parse a simple array (depth=1)
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
static QgsFeatureList stringToFeatureList(const QString &string, const QgsFields &fields, QTextCodec *encoding)
Attempts to parse a string representing a collection of features using OGR.
static QgsFields stringToFields(const QString &string, QTextCodec *encoding)
Attempts to retrieve the fields from a string representing a collection of features using OGR.
QgsRelationManager * relationManager
Definition: qgsproject.h:115
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
static Qgis::WkbType flatType(Qgis::WkbType type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:629
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:3563
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:920
#define FID_IS_NULL(fid)
Definition: qgsfeatureid.h:30
const QgsField & field
Definition: qgsfield.h:501
QgsSQLStatement::Node * parse(const QString &str, QString &parserErrorMsg, bool allowFragments)
const QgsCoordinateReferenceSystem & crs
int precision