QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsfeature.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeature.h - Spatial Feature Class
3  --------------------------------------
4 Date : 09-Sep-2003
5 Copyright : (C) 2003 by Gary E.Sherman
6 email : sherman at mrcc.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 #ifndef QGSFEATURE_H
17 #define QGSFEATURE_H
18 
19 #include "qgis_core.h"
20 #include "qgis_sip.h"
21 
22 #include <QExplicitlySharedDataPointer>
23 #include <QList>
24 #include <QMap>
25 #include <QSet>
26 #include <QString>
27 #include <QVariant>
28 #include <QVector>
29 
30 #include "qgsattributes.h"
31 #include "qgsfields.h"
32 #include "qgsfeatureid.h"
33 #include <memory>
34 class QgsFeature;
35 class QgsFeaturePrivate;
36 class QgsField;
37 class QgsGeometry;
38 class QgsRectangle;
40 class QgsSymbol;
41 
42 /***************************************************************************
43  * This class is considered CRITICAL and any change MUST be accompanied with
44  * full unit tests in testqgsfeature.cpp.
45  * See details in QEP #17
46  ****************************************************************************/
47 
48 
55 class CORE_EXPORT QgsFeature
56 {
57 #ifdef SIP_RUN
58 #if (SIP_VERSION >= 0x040900 && SIP_VERSION < 0x040c01)
59 #define sipType_QVariant ((sipWrapperType *) sipTypeAsPyTypeObject (sipType_QVariant))
60 #endif
61 #endif
62  Q_GADGET
63 
64  Q_PROPERTY( QgsFeatureId id READ id WRITE setId )
65  Q_PROPERTY( QgsAttributes attributes READ attributes WRITE setAttributes )
66  Q_PROPERTY( QgsFields fields READ fields WRITE setFields )
67  Q_PROPERTY( QgsGeometry geometry READ geometry WRITE setGeometry )
68 
69  public:
70 
71 #ifdef SIP_RUN
72  SIP_PYOBJECT __iter__();
73  % MethodCode
74  QgsAttributes attributes = sipCpp->attributes();
75  PyObject *attrs = sipConvertFromType( &attributes, sipType_QgsAttributes, Py_None );
76  sipRes = PyObject_GetIter( attrs );
77  % End
78 
79  SIP_PYOBJECT __getitem__( int key );
80  % MethodCode
81  QgsAttributes attrs = sipCpp->attributes();
82  if ( a0 < 0 || a0 >= attrs.count() )
83  {
84  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
85  sipIsErr = 1;
86  }
87  else
88  {
89  QVariant *v = new QVariant( attrs.at( a0 ) );
90  sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
91  }
92  % End
93 
94  SIP_PYOBJECT __getitem__( const QString &name );
95  % MethodCode
96  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
97  if ( fieldIdx == -1 )
98  {
99  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
100  sipIsErr = 1;
101  }
102  else
103  {
104  QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
105  sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
106  }
107  % End
108 
109  void __setitem__( int key, QVariant value / GetWrapper / );
110  % MethodCode
111  bool rv;
112 
113  if ( a1Wrapper == Py_None )
114  {
115  rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
116  }
117  else
118  {
119  rv = sipCpp->setAttribute( a0, *a1 );
120  }
121 
122  if ( !rv )
123  {
124  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
125  sipIsErr = 1;
126  }
127  % End
128 
129  void __setitem__( const QString &key, QVariant value / GetWrapper / );
130  % MethodCode
131  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
132  if ( fieldIdx == -1 )
133  {
134  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
135  sipIsErr = 1;
136  }
137  else
138  {
139  if ( a1Wrapper == Py_None )
140  {
141  sipCpp->setAttribute( *a0, QVariant( QVariant::Int ) );
142  }
143  else
144  {
145  sipCpp->setAttribute( fieldIdx, *a1 );
146  }
147  }
148  % End
149 
150  void __delitem__( int key );
151  % MethodCode
152  if ( a0 >= 0 && a0 < sipCpp->attributes().count() )
153  sipCpp->deleteAttribute( a0 );
154  else
155  {
156  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
157  sipIsErr = 1;
158  }
159  % End
160 
161  void __delitem__( const QString &name );
162  % MethodCode
163  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
164  if ( fieldIdx == -1 )
165  {
166  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
167  sipIsErr = 1;
168  }
169  else
170  sipCpp->deleteAttribute( fieldIdx );
171  % End
172 
173  long __hash__() const;
174  % MethodCode
175  sipRes = qHash( *sipCpp );
176  % End
177 #endif
178 
183 #ifndef SIP_RUN
185 #else
186  QgsFeature( qint64 id = FID_NULL );
187 #endif
188 
194 #ifndef SIP_RUN
195  QgsFeature( const QgsFields &fields, QgsFeatureId id = FID_NULL );
196 #else
197  QgsFeature( const QgsFields &fields, qint64 id = FID_NULL );
198 #endif
199 
203  QgsFeature( const QgsFeature &rhs );
204 
208  QgsFeature &operator=( const QgsFeature &rhs );
209 
213  bool operator==( const QgsFeature &other ) const;
214 
218  bool operator!=( const QgsFeature &other ) const;
219 
220  virtual ~QgsFeature();
221 
226  QgsFeatureId id() const;
227 
236  void setId( QgsFeatureId id );
237 
254  QgsAttributes attributes() const;
255 
256 #ifndef SIP_RUN
257 
267  QVariantMap attributeMap() const;
268 #else
269 
281  SIP_PYOBJECT attributeMap() const SIP_TYPEHINT( Dict[str, Optional[object]] );
282  % MethodCode
283  const int fieldSize = sipCpp->fields().size();
284  const int attributeSize = sipCpp->attributes().size();
285  if ( fieldSize == 0 && attributeSize != 0 )
286  {
287  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Field definition has not been set for feature" ).toUtf8().constData() );
288  sipIsErr = 1;
289  }
290  else if ( fieldSize != attributeSize )
291  {
292  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Feature attribute size (%1) does not match number of fields (%2)" ).arg( attributeSize ).arg( fieldSize ).toUtf8().constData() );
293  sipIsErr = 1;
294  }
295  else
296  {
297  QVariantMap *v = new QVariantMap( sipCpp->attributeMap() );
298  const sipTypeDef *qvariantmap_type = sipFindType( "QMap<QString,QVariant>" );
299  sipRes = sipConvertFromNewType( v, qvariantmap_type, Py_None );
300  }
301  % End
302 #endif
303 
308  int attributeCount() const;
309 
326  void setAttributes( const QgsAttributes &attrs );
327 
328 #ifndef SIP_RUN
329 
340  bool setAttribute( int field, const QVariant &attr );
341 #else
342 
367  bool setAttribute( int field, const QVariant &attr / GetWrapper / );
368  % MethodCode
369  bool rv;
370 
371  if ( a1Wrapper == Py_None )
372  {
373  rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
374  }
375  else
376  {
377  rv = sipCpp->setAttribute( a0, *a1 );
378  }
379 
380  if ( !rv )
381  {
382  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
383  sipIsErr = 1;
384  }
385 
386  sipRes = rv;
387  % End
388 #endif
389 
399  void initAttributes( int fieldCount );
400 
414  void resizeAttributes( int fieldCount );
415 
422  void padAttributes( int count );
423 
424 #ifndef SIP_RUN
425 
433  void deleteAttribute( int field );
434 #else
435 
460  void deleteAttribute( int field );
461  % MethodCode
462  if ( a0 >= 0 && a0 < sipCpp->attributes().count() )
463  sipCpp->deleteAttribute( a0 );
464  else
465  {
466  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
467  sipIsErr = 1;
468  }
469  % End
470 #endif
471 
480  bool isValid() const;
481 
489  void setValid( bool validity );
490 
495  bool hasGeometry() const;
496 
503  QgsGeometry geometry() const;
504 
514  void setGeometry( const QgsGeometry &geometry );
515 
546 #ifndef SIP_RUN
547  void setGeometry( std::unique_ptr< QgsAbstractGeometry > geometry );
548 #else
549  void setGeometry( QgsAbstractGeometry *geometry SIP_TRANSFER );
550  % MethodCode
551  sipCpp->setGeometry( std::unique_ptr< QgsAbstractGeometry>( a0 ) );
552  % End
553 #endif
554 
560  void clearGeometry();
561 
568  void setFields( const QgsFields &fields, bool initAttributes = false SIP_PYARGDEFAULT( true ) );
569 
574  QgsFields fields() const;
575 
576 #ifndef SIP_RUN
577 
592  bool setAttribute( const QString &name, const QVariant &value );
593 #else
594 
621  void setAttribute( const QString &name, const QVariant &value / GetWrapper / );
622  % MethodCode
623  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
624  if ( fieldIdx == -1 )
625  {
626  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
627  sipIsErr = 1;
628  }
629  else
630  {
631  if ( a1Wrapper == Py_None )
632  {
633  sipCpp->setAttribute( *a0, QVariant( QVariant::Int ) );
634  }
635  else
636  {
637  sipCpp->setAttribute( fieldIdx, *a1 );
638  }
639  }
640  % End
641 #endif
642 
643 #ifndef SIP_RUN
644 
654  bool deleteAttribute( const QString &name );
655 #else
656 
686  bool deleteAttribute( const QString &name );
687  % MethodCode
688  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
689  if ( fieldIdx == -1 )
690  {
691  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
692  sipIsErr = 1;
693  sipRes = false;
694  }
695  else
696  {
697  sipCpp->deleteAttribute( fieldIdx );
698  sipRes = true;
699  }
700  % End
701 #endif
702 
703 #ifndef SIP_RUN
704 
714  QVariant attribute( const QString &name ) const;
715 #else
716 
742  SIP_PYOBJECT attribute( const QString &name ) const;
743  % MethodCode
744  int fieldIdx = sipCpp->fieldNameIndex( *a0 );
745  if ( fieldIdx == -1 )
746  {
747  PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
748  sipIsErr = 1;
749  }
750  else
751  {
752  QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
753  sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
754  }
755  % End
756 #endif
757 
758 #ifndef SIP_RUN
759 
767  QVariant attribute( int fieldIdx ) const;
768 #else
769 
794  SIP_PYOBJECT attribute( int fieldIdx ) const;
795  % MethodCode
796  {
797  if ( a0 < 0 || a0 >= sipCpp->attributes().count() )
798  {
799  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
800  sipIsErr = 1;
801  }
802  else
803  {
804  QVariant *v = new QVariant( sipCpp->attribute( a0 ) );
805  sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
806  }
807  }
808  % End
809 #endif
810 
811 
812 #ifndef SIP_RUN
813 
820  bool isUnsetValue( int fieldIdx ) const;
821 #else
822 
830  bool isUnsetValue( int fieldIdx ) const;
831  % MethodCode
832  {
833  if ( a0 < 0 || a0 >= sipCpp->attributes().count() )
834  {
835  PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
836  sipIsErr = 1;
837  }
838  else
839  {
840  sipRes = sipCpp->isUnsetValue( a0 );
841  }
842  }
843  % End
844 #endif
845 
851  const QgsSymbol *embeddedSymbol() const;
852 
860  void setEmbeddedSymbol( QgsSymbol *symbol SIP_TRANSFER );
861 
871  int fieldNameIndex( const QString &fieldName ) const;
872 
882  int approximateMemoryUsage() const;
883 
885  operator QVariant() const
886  {
887  return QVariant::fromValue( *this );
888  }
889 
890  private:
891 
892  QExplicitlySharedDataPointer<QgsFeaturePrivate> d;
893 
894 }; // class QgsFeature
895 
897 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsFeature &feature ) SIP_SKIP;
899 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsFeature &feature ) SIP_SKIP;
900 
901 // key = feature id, value = changed attributes
902 #ifndef SIP_RUN
903 typedef QMap<QgsFeatureId, QgsAttributeMap> QgsChangedAttributesMap;
904 #else
905 typedef QMap<qint64, QMap<int, QVariant> > QgsChangedAttributesMap;
906 #endif
907 
908 #include "qgsgeometry.h"
909 
910 // key = feature id, value = changed geometry
911 #ifndef SIP_RUN
912 typedef QMap<QgsFeatureId, QgsGeometry> QgsGeometryMap;
913 #else
914 typedef QMap<qint64, QgsGeometry> QgsGeometryMap;
915 #endif
916 
917 typedef QList<QgsFeature> QgsFeatureList;
918 
919 CORE_EXPORT uint qHash( const QgsFeature &key, uint seed = 0 ) SIP_SKIP;
920 
923 
924 #endif
Abstract base class for all geometries.
A vector of attributes.
Definition: qgsattributes.h:59
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
Container of fields for a vector layer.
Definition: qgsfields.h:45
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:94
#define str(x)
Definition: qgis.cpp:38
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:232
#define SIP_PYARGDEFAULT(value)
Definition: qgis_sip.h:146
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_TRANSFER
Definition: qgis_sip.h:36
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:912
CORE_EXPORT uint qHash(const QgsFeature &key, uint seed=0)
Definition: qgsfeature.cpp:444
CORE_EXPORT QDataStream & operator>>(QDataStream &in, QgsFeature &feature)
Reads a feature from stream in into feature. QGIS version compatibility is not guaranteed.
Definition: qgsfeature.cpp:430
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:903
CORE_EXPORT QDataStream & operator<<(QDataStream &out, const QgsFeature &feature)
Writes the feature to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsfeature.cpp:413
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917
#define FID_NULL
Definition: qgsfeatureid.h:29
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
bool operator!=(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)