QGIS API Documentation 3.28.14-Firenze (exported)
Loading...
Searching...
No Matches
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 mTransform.setDestinationCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
46}
47
49{
50 mLayer = vectorLayer;
51 if ( vectorLayer )
52 {
53 mCrs = vectorLayer->crs();
54 mTransform.setSourceCrs( mCrs );
55 }
56}
57
59{
60 return mLayer.data();
61}
62
64{
65 mCrs = crs;
66 mTransform.setSourceCrs( mCrs );
67}
68
73
74QString QgsJsonExporter::exportFeature( const QgsFeature &feature, const QVariantMap &extraProperties,
75 const QVariant &id, int indent ) const
76{
77 return QString::fromStdString( exportFeatureToJsonObject( feature, extraProperties, id ).dump( indent ) );
78}
79
80json QgsJsonExporter::exportFeatureToJsonObject( const QgsFeature &feature, const QVariantMap &extraProperties, const QVariant &id ) const
81{
82 json featureJson
83 {
84 { "type", "Feature" },
85 };
86 if ( id.isValid() )
87 {
88 bool ok = false;
89 auto intId = id.toLongLong( &ok );
90 if ( ok )
91 {
92 featureJson["id"] = intId;
93 }
94 else
95 {
96 featureJson["id"] = id.toString().toStdString();
97 }
98 }
99 else if ( FID_IS_NULL( feature.id() ) )
100 {
101 featureJson["id"] = nullptr;
102 }
103 else
104 {
105 featureJson["id"] = feature.id();
106 }
107
108 QgsGeometry geom = feature.geometry();
109 if ( !geom.isNull() && mIncludeGeometry )
110 {
111 if ( mCrs.isValid() )
112 {
113 try
114 {
115 QgsGeometry transformed = geom;
116 if ( mTransformGeometries && transformed.transform( mTransform ) == Qgis::GeometryOperationResult::Success )
117 geom = transformed;
118 }
119 catch ( QgsCsException &cse )
120 {
121 Q_UNUSED( cse )
122 }
123 }
124 QgsRectangle box = geom.boundingBox();
125
127 {
128 featureJson[ "bbox" ] =
129 {
130 qgsRound( box.xMinimum(), mPrecision ),
131 qgsRound( box.yMinimum(), mPrecision ),
132 qgsRound( box.xMaximum(), mPrecision ),
133 qgsRound( box.yMaximum(), mPrecision )
134 };
135 }
136 featureJson[ "geometry" ] = geom.asJsonObject( mPrecision );
137 }
138 else
139 {
140 featureJson[ "geometry" ] = nullptr;
141 }
142
143 // build up properties element
144 int attributeCounter { 0 };
145 json properties;
146 if ( mIncludeAttributes || !extraProperties.isEmpty() )
147 {
148 //read all attribute values from the feature
149 if ( mIncludeAttributes )
150 {
151 QgsFields fields = mLayer ? mLayer->fields() : feature.fields();
152 // List of formatters through we want to pass the values
153 QStringList formattersAllowList;
154 formattersAllowList << QStringLiteral( "KeyValue" )
155 << QStringLiteral( "List" )
156 << QStringLiteral( "ValueRelation" )
157 << QStringLiteral( "ValueMap" );
158
159 for ( int i = 0; i < fields.count(); ++i )
160 {
161 if ( ( !mAttributeIndexes.isEmpty() && !mAttributeIndexes.contains( i ) ) || mExcludedAttributeIndexes.contains( i ) )
162 continue;
163
164 QVariant val = feature.attributes().at( i );
165
166 if ( mLayer )
167 {
168 const QgsEditorWidgetSetup setup = fields.at( i ).editorWidgetSetup();
170 if ( formattersAllowList.contains( fieldFormatter->id() ) )
171 val = fieldFormatter->representValue( mLayer.data(), i, setup.config(), QVariant(), val );
172 }
173
174 QString name = fields.at( i ).name();
175 if ( mAttributeDisplayName )
176 {
177 name = mLayer->attributeDisplayName( i );
178 }
179 properties[ name.toStdString() ] = QgsJsonUtils::jsonFromVariant( val );
180 attributeCounter++;
181 }
182 }
183
184 if ( !extraProperties.isEmpty() )
185 {
186 QVariantMap::const_iterator it = extraProperties.constBegin();
187 for ( ; it != extraProperties.constEnd(); ++it )
188 {
189 properties[ it.key().toStdString() ] = QgsJsonUtils::jsonFromVariant( it.value() );
190 attributeCounter++;
191 }
192 }
193
194 // related attributes
195 if ( mLayer && mIncludeRelatedAttributes )
196 {
197 QList< QgsRelation > relations = QgsProject::instance()->relationManager()->referencedRelations( mLayer.data() );
198 for ( const auto &relation : std::as_const( relations ) )
199 {
200 QgsFeatureRequest req = relation.getRelatedFeaturesRequest( feature );
202 QgsVectorLayer *childLayer = relation.referencingLayer();
203 json relatedFeatureAttributes;
204 if ( childLayer )
205 {
206 QgsFeatureIterator it = childLayer->getFeatures( req );
207 QVector<QVariant> attributeWidgetCaches;
208 int fieldIndex = 0;
209 const QgsFields fields { childLayer->fields() };
210 for ( const QgsField &field : fields )
211 {
214 attributeWidgetCaches.append( fieldFormatter->createCache( childLayer, fieldIndex, setup.config() ) );
215 fieldIndex++;
216 }
217 QgsFeature relatedFet;
218 while ( it.nextFeature( relatedFet ) )
219 {
220 relatedFeatureAttributes += QgsJsonUtils::exportAttributesToJsonObject( relatedFet, childLayer, attributeWidgetCaches );
221 }
222 }
223 properties[ relation.name().toStdString() ] = relatedFeatureAttributes;
224 attributeCounter++;
225 }
226 }
227 }
228 featureJson[ "properties" ] = properties;
229 return featureJson;
230}
231
232QString QgsJsonExporter::exportFeatures( const QgsFeatureList &features, int indent ) const
233{
234 return QString::fromStdString( exportFeaturesToJsonObject( features ).dump( indent ) );
235}
236
238{
239 json data
240 {
241 { "type", "FeatureCollection" },
242 { "features", json::array() }
243 };
244 for ( const QgsFeature &feature : std::as_const( features ) )
245 {
246 data["features"].push_back( exportFeatureToJsonObject( feature ) );
247 }
248 return data;
249}
250
251//
252// QgsJsonUtils
253//
254
255QgsFeatureList QgsJsonUtils::stringToFeatureList( const QString &string, const QgsFields &fields, QTextCodec *encoding )
256{
257 if ( !encoding )
258 encoding = QTextCodec::codecForName( "UTF-8" );
259
260 return QgsOgrUtils::stringToFeatureList( string, fields, encoding );
261}
262
263QgsFields QgsJsonUtils::stringToFields( const QString &string, QTextCodec *encoding )
264{
265 if ( !encoding )
266 encoding = QTextCodec::codecForName( "UTF-8" );
267
268 return QgsOgrUtils::stringToFields( string, encoding );
269}
270
271QString QgsJsonUtils::encodeValue( const QVariant &value )
272{
273 if ( QgsVariantUtils::isNull( value ) )
274 return QStringLiteral( "null" );
275
276 switch ( value.type() )
277 {
278 case QVariant::Int:
279 case QVariant::UInt:
280 case QVariant::LongLong:
281 case QVariant::ULongLong:
282 case QVariant::Double:
283 return value.toString();
284
285 case QVariant::Bool:
286 return value.toBool() ? "true" : "false";
287
288 case QVariant::StringList:
289 case QVariant::List:
290 case QVariant::Map:
291 return QString::fromUtf8( QJsonDocument::fromVariant( value ).toJson( QJsonDocument::Compact ) );
292
293 default:
294 case QVariant::String:
295 QString v = value.toString()
296 .replace( '\\', QLatin1String( "\\\\" ) )
297 .replace( '"', QLatin1String( "\\\"" ) )
298 .replace( '\r', QLatin1String( "\\r" ) )
299 .replace( '\b', QLatin1String( "\\b" ) )
300 .replace( '\t', QLatin1String( "\\t" ) )
301 .replace( '/', QLatin1String( "\\/" ) )
302 .replace( '\n', QLatin1String( "\\n" ) );
303
304 return v.prepend( '"' ).append( '"' );
305 }
306}
307
308QString QgsJsonUtils::exportAttributes( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
309{
310 QgsFields fields = feature.fields();
311 QString attrs;
312 for ( int i = 0; i < fields.count(); ++i )
313 {
314 if ( i > 0 )
315 attrs += QLatin1String( ",\n" );
316
317 QVariant val = feature.attributes().at( i );
318
319 if ( layer )
320 {
321 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
323 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
324 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
325 }
326
327 attrs += encodeValue( fields.at( i ).name() ) + ':' + encodeValue( val );
328 }
329 return attrs.prepend( '{' ).append( '}' );
330}
331
332QVariantList QgsJsonUtils::parseArray( const QString &json, QVariant::Type type )
333{
334 QString errorMessage;
335 QVariantList result;
336 try
337 {
338 const auto jObj( json::parse( json.toStdString() ) );
339 if ( ! jObj.is_array() )
340 {
341 throw json::parse_error::create( 0, 0, QStringLiteral( "JSON value must be an array" ).toStdString() );
342 }
343 for ( const auto &item : jObj )
344 {
345 // Create a QVariant from the array item
346 QVariant v;
347 if ( item.is_number_integer() )
348 {
349 v = item.get<int>();
350 }
351 else if ( item.is_number_unsigned() )
352 {
353 v = item.get<unsigned>();
354 }
355 else if ( item.is_number_float() )
356 {
357 // Note: it's a double and not a float on purpose
358 v = item.get<double>();
359 }
360 else if ( item.is_string() )
361 {
362 v = QString::fromStdString( item.get<std::string>() );
363 }
364 else if ( item.is_boolean() )
365 {
366 v = item.get<bool>();
367 }
368 else if ( item.is_null() )
369 {
370 // Fallback to int
371 v = QVariant( type == QVariant::Type::Invalid ? QVariant::Type::Int : type );
372 }
373
374 // If a destination type was specified (it's not invalid), try to convert
375 if ( type != QVariant::Invalid )
376 {
377 if ( ! v.convert( static_cast<int>( type ) ) )
378 {
379 QgsLogger::warning( QStringLiteral( "Cannot convert json array element to specified type, ignoring: %1" ).arg( v.toString() ) );
380 }
381 else
382 {
383 result.push_back( v );
384 }
385 }
386 else
387 {
388 result.push_back( v );
389 }
390 }
391 }
392 catch ( json::parse_error &ex )
393 {
394 errorMessage = ex.what();
395 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( ex.what(), json ) );
396 }
397
398 return result;
399}
400
401json QgsJsonUtils::jsonFromVariant( const QVariant &val )
402{
403 if ( QgsVariantUtils::isNull( val ) )
404 {
405 return nullptr;
406 }
407 json j;
408 if ( val.type() == QVariant::Type::Map )
409 {
410 const QVariantMap &vMap = val.toMap();
411 json jMap = json::object();
412 for ( auto it = vMap.constBegin(); it != vMap.constEnd(); it++ )
413 {
414 jMap[ it.key().toStdString() ] = jsonFromVariant( it.value() );
415 }
416 j = jMap;
417 }
418 else if ( val.type() == QVariant::Type::List || val.type() == QVariant::Type::StringList )
419 {
420 const QVariantList &vList = val.toList();
421 json jList = json::array();
422 for ( const auto &v : vList )
423 {
424 jList.push_back( jsonFromVariant( v ) );
425 }
426 j = jList;
427 }
428 else
429 {
430 switch ( val.userType() )
431 {
432 case QMetaType::Int:
433 case QMetaType::UInt:
434 case QMetaType::LongLong:
435 case QMetaType::ULongLong:
436 j = val.toLongLong();
437 break;
438 case QMetaType::Double:
439 case QMetaType::Float:
440 j = val.toDouble();
441 break;
442 case QMetaType::Bool:
443 j = val.toBool();
444 break;
445 case QMetaType::QByteArray:
446 j = val.toByteArray().toBase64().toStdString();
447 break;
448 default:
449 j = val.toString().toStdString();
450 break;
451 }
452 }
453 return j;
454}
455
456QVariant QgsJsonUtils::parseJson( const std::string &jsonString )
457{
458 QString error;
459 const QVariant res = parseJson( jsonString, error );
460
461 if ( !error.isEmpty() )
462 {
463 QgsLogger::warning( QStringLiteral( "Cannot parse json (%1): %2" ).arg( error,
464 QString::fromStdString( jsonString ) ) );
465 }
466 return res;
467}
468
469QVariant QgsJsonUtils::parseJson( const std::string &jsonString, QString &error )
470{
471 // tracks whether entire json string is a primitive
472 bool isPrimitive = true;
473
474 std::function<QVariant( json )> _parser { [ & ]( json jObj ) -> QVariant {
475 QVariant result;
476 if ( jObj.is_array() )
477 {
478 isPrimitive = false;
479 QVariantList results;
480 results.reserve( jObj.size() );
481 for ( const auto &item : jObj )
482 {
483 results.push_back( _parser( item ) );
484 }
485 result = results;
486 }
487 else if ( jObj.is_object() )
488 {
489 isPrimitive = false;
490 QVariantMap results;
491 for ( const auto &item : jObj.items() )
492 {
493 const auto key { QString::fromStdString( item.key() ) };
494 const auto value { _parser( item.value() ) };
495 results[ key ] = value;
496 }
497 result = results;
498 }
499 else
500 {
501 if ( jObj.is_number_unsigned() )
502 {
503 // Try signed int and long long first, fall back
504 // onto unsigned long long
505 const qulonglong num { jObj.get<qulonglong>() };
506 if ( num <= std::numeric_limits<int>::max() )
507 {
508 result = static_cast<int>( num );
509 }
510 else if ( num <= std::numeric_limits<qlonglong>::max() )
511 {
512 result = static_cast<qlonglong>( num );
513 }
514 else
515 {
516 result = num;
517 }
518 }
519 else if ( jObj.is_number_integer() )
520 {
521 const qlonglong num { jObj.get<qlonglong>() };
522 if ( num <= std::numeric_limits<int>::max() && num >= std::numeric_limits<int>::lowest() )
523 {
524 result = static_cast<int>( num );
525 }
526 else
527 {
528 result = num;
529 }
530 }
531 else if ( jObj.is_boolean() )
532 {
533 result = jObj.get<bool>();
534 }
535 else if ( jObj.is_number_float() )
536 {
537 // Note: it's a double and not a float on purpose
538 result = jObj.get<double>();
539 }
540 else if ( jObj.is_string() )
541 {
542 if ( isPrimitive && jObj.get<std::string>().length() == 0 )
543 {
544 result = QString::fromStdString( jObj.get<std::string>() ).append( "\"" ).insert( 0, "\"" );
545 }
546 else
547 {
548 result = QString::fromStdString( jObj.get<std::string>() );
549 }
550 }
551 else if ( jObj.is_null() )
552 {
553 // Do nothing (leave invalid)
554 }
555 }
556 return result;
557 }
558 };
559
560 error.clear();
561 try
562 {
563 const json j = json::parse( jsonString );
564 return _parser( j );
565 }
566 catch ( json::parse_error &ex )
567 {
568 error = QString::fromStdString( ex.what() );
569 }
570 return QVariant();
571}
572
573QVariant QgsJsonUtils::parseJson( const QString &jsonString )
574{
575 return parseJson( jsonString.toStdString() );
576}
577
578json QgsJsonUtils::exportAttributesToJsonObject( const QgsFeature &feature, QgsVectorLayer *layer, const QVector<QVariant> &attributeWidgetCaches )
579{
580 QgsFields fields = feature.fields();
581 json attrs;
582 for ( int i = 0; i < fields.count(); ++i )
583 {
584 QVariant val = feature.attributes().at( i );
585
586 if ( layer )
587 {
588 QgsEditorWidgetSetup setup = layer->fields().at( i ).editorWidgetSetup();
590 if ( fieldFormatter != QgsApplication::fieldFormatterRegistry()->fallbackFieldFormatter() )
591 val = fieldFormatter->representValue( layer, i, setup.config(), attributeWidgetCaches.count() >= i ? attributeWidgetCaches.at( i ) : QVariant(), val );
592 }
593 attrs[fields.at( i ).name().toStdString()] = jsonFromVariant( val );
594 }
595 return attrs;
596}
@ 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.
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
QgsFeatureId id
Definition qgsfeature.h:64
QgsGeometry geometry
Definition qgsfeature.h:67
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:51
QString name
Definition qgsfield.h:60
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.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
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.
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.
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:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
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 Type flatType(Type type)
Returns the flat type for a WKB type.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition qgis.h:2581
QList< QgsFeature > QgsFeatureList
Definition qgsfeature.h:922
#define FID_IS_NULL(fid)
const QgsField & field
Definition qgsfield.h:476
const QgsCoordinateReferenceSystem & crs
int precision