QGIS API Documentation 4.1.0-Master (31622b25bb0)
Loading...
Searching...
No Matches
qgsfeature.h
Go to the documentation of this file.
1/***************************************************************************
2 qgsfeature.h - Spatial Feature Class
3 --------------------------------------
4Date : 09-Sep-2003
5Copyright : (C) 2003 by Gary E.Sherman
6email : 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 <memory>
20
21#include "qgis_core.h"
22#include "qgis_sip.h"
23#include "qgsattributes.h"
24#include "qgsfeatureid.h"
25#include "qgsfields.h"
26#include "qgsvariantutils.h"
27
28#include <QExplicitlySharedDataPointer>
29#include <QList>
30#include <QMap>
31#include <QSet>
32#include <QString>
33#include <QVariant>
34#include <QVector>
35
36using namespace Qt::StringLiterals;
37
38class QgsFeature;
39class QgsFeaturePrivate;
40class QgsField;
41class QgsGeometry;
42class QgsRectangle;
44class QgsSymbol;
45
46/***************************************************************************
47 * This class is considered CRITICAL and any change MUST be accompanied with
48 * full unit tests in testqgsfeature.cpp.
49 * See details in QEP #17
50 ****************************************************************************/
51
52
59class CORE_EXPORT QgsFeature
60{
61 Q_GADGET
62
63 Q_PROPERTY( QgsFeatureId id READ id WRITE setId )
65 Q_PROPERTY( QgsFields fields READ fields WRITE setFields )
66 Q_PROPERTY( QgsGeometry geometry READ geometry WRITE setGeometry )
67
68 public:
69#ifdef SIP_RUN
70 // clang-format off
71 SIP_PYOBJECT __iter__() SIP_HOLDGIL;
72 // clang-format on
73 % MethodCode
75 PyObject *attrs = sipConvertFromType( &attributes, sipType_QgsAttributes, Py_None );
76 sipRes = PyObject_GetIter( attrs );
77 // PyObject_GetIter has added a ref to attrs - we need to decrement the ref from sipConvertFromType,
78 // so that the garbage collector will delete attrs when the iterator is deleted
79 Py_DECREF( attrs );
80 % End
81#endif
82
83#ifdef SIP_PYQT5_RUN
84#ifdef SIP_RUN
85// clang-format off
86 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
87 % MethodCode
88 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
89 {
90 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
91 sipIsErr = 1;
92 }
93 else
94 {
95 const QVariant v = sipCpp->attribute( a0 );
96 if ( !v.isValid() )
97 {
98 Py_INCREF( Py_None );
99 sipRes = Py_None;
100 }
101 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
102 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
103 {
104 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
105 PyObject *args = PyTuple_Pack( 1, vartype );
106 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
107 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
108 Py_DECREF( args );
109 Py_DECREF( vartype );
110 }
111 else
112 {
113 switch ( v.userType() )
114 {
115 case QMetaType::Type::Int:
116 sipRes = PyLong_FromLong( v.toInt() );
117 break;
118
119 case QMetaType::Type::UInt:
120 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
121 break;
122
123 case QMetaType::Type::Long:
124 case QMetaType::Type::LongLong:
125 sipRes = PyLong_FromLongLong( v.toLongLong() );
126 break;
127
128 case QMetaType::Type::ULong:
129 case QMetaType::Type::ULongLong:
130 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
131 break;
132
133 case QMetaType::Type::Bool:
134 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
135 break;
136
137 case QMetaType::Type::Float:
138 case QMetaType::Type::Double:
139 sipRes = PyFloat_FromDouble( v.toDouble() );
140 break;
141
142 case QMetaType::Type::QString:
143 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
144 break;
145
146 default:
147 {
148 QVariant *newV = new QVariant( v );
149 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
150 break;
151 }
152 }
153 }
154 }
155 % End
156
157 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
158 % MethodCode
159 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
160 if ( fieldIdx == -1 )
161 {
162 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
163 sipIsErr = 1;
164 }
165 else
166 {
167 const QVariant v = sipCpp->attribute( fieldIdx );
168 if ( !v.isValid() )
169 {
170 Py_INCREF( Py_None );
171 sipRes = Py_None;
172 }
173 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
174 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
175 {
176 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
177 PyObject *args = PyTuple_Pack( 1, vartype );
178 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
179 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
180 Py_DECREF( args );
181 Py_DECREF( vartype );
182 }
183 else
184 {
185 switch ( v.userType() )
186 {
187 case QMetaType::Type::Int:
188 sipRes = PyLong_FromLong( v.toInt() );
189 break;
190
191 case QMetaType::Type::UInt:
192 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
193 break;
194
195 case QMetaType::Type::Long:
196 case QMetaType::Type::LongLong:
197 sipRes = PyLong_FromLongLong( v.toLongLong() );
198 break;
199
200 case QMetaType::Type::ULong:
201 case QMetaType::Type::ULongLong:
202 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
203 break;
204
205 case QMetaType::Type::Bool:
206 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
207 break;
208
209 case QMetaType::Type::Float:
210 case QMetaType::Type::Double:
211 sipRes = PyFloat_FromDouble( v.toDouble() );
212 break;
213
214 case QMetaType::Type::QString:
215 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
216 break;
217
218 default:
219 {
220 QVariant *newV = new QVariant( v );
221 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
222 break;
223 }
224 }
225 }
226 }
227 % End
228// clang-format on
229#endif
230#endif
231
232#ifdef SIP_PYQT6_RUN
233#ifdef SIP_RUN
234// clang-format off
235 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
236 % MethodCode
237 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
238 {
239 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
240 sipIsErr = 1;
241 }
242 else
243 {
244 const QVariant v = sipCpp->attribute( a0 );
245 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
246 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
247 {
248 Py_INCREF( Py_None );
249 sipRes = Py_None;
250 }
251 else
252 {
253 switch ( v.userType() )
254 {
255 case QMetaType::Type::Int:
256 sipRes = PyLong_FromLong( v.toInt() );
257 break;
258
259 case QMetaType::Type::UInt:
260 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
261 break;
262
263 case QMetaType::Type::Long:
264 case QMetaType::Type::LongLong:
265 sipRes = PyLong_FromLongLong( v.toLongLong() );
266 break;
267
268 case QMetaType::Type::ULong:
269 case QMetaType::Type::ULongLong:
270 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
271 break;
272
273 case QMetaType::Type::Bool:
274 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
275 break;
276
277 case QMetaType::Type::Float:
278 case QMetaType::Type::Double:
279 sipRes = PyFloat_FromDouble( v.toDouble() );
280 break;
281
282 case QMetaType::Type::QString:
283 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
284 break;
285
286 default:
287 {
288 QVariant *newV = new QVariant( v );
289 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
290 break;
291 }
292 }
293 }
294 }
295 % End
296
297 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
298 % MethodCode
299 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
300 if ( fieldIdx == -1 )
301 {
302 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
303 sipIsErr = 1;
304 }
305 else
306 {
307 const QVariant v = sipCpp->attribute( fieldIdx );
308 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
309 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
310 {
311 Py_INCREF( Py_None );
312 sipRes = Py_None;
313 }
314 else
315 {
316 switch ( v.userType() )
317 {
318 case QMetaType::Type::Int:
319 sipRes = PyLong_FromLong( v.toInt() );
320 break;
321
322 case QMetaType::Type::UInt:
323 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
324 break;
325
326 case QMetaType::Type::Long:
327 case QMetaType::Type::LongLong:
328 sipRes = PyLong_FromLongLong( v.toLongLong() );
329 break;
330
331 case QMetaType::Type::ULong:
332 case QMetaType::Type::ULongLong:
333 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
334 break;
335
336 case QMetaType::Type::Bool:
337 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
338 break;
339
340 case QMetaType::Type::Float:
341 case QMetaType::Type::Double:
342 sipRes = PyFloat_FromDouble( v.toDouble() );
343 break;
344
345 case QMetaType::Type::QString:
346 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
347 break;
348
349 default:
350 {
351 QVariant *newV = new QVariant( v );
352 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
353 break;
354 }
355 }
356 }
357 }
358 % End
359// clang-format on
360#endif
361#endif
362
363#ifdef SIP_RUN
364// clang-format off
365 void __setitem__( int key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
366 % MethodCode
367 bool rv;
368
369 if ( a1 == Py_None )
370 {
371 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
372 }
373 else if ( PyBool_Check( a1 ) )
374 {
375 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
376 }
377 else if ( PyLong_Check( a1 ) )
378 {
379 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
380 }
381 else if ( PyFloat_Check( a1 ) )
382 {
383 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
384 }
385 else if ( PyUnicode_Check( a1 ) )
386 {
387 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
388 }
389 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
390 {
391 int state;
392 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
393 if ( sipIsErr )
394 {
395 rv = false;
396 }
397 else
398 {
399 rv = sipCpp->setAttribute( a0, *qvariant );
400 }
401 sipReleaseType( qvariant, sipType_QVariant, state );
402 }
403 else
404 {
405 rv = false;
406 }
407
408 if ( !rv )
409 {
410 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
411 sipIsErr = 1;
412 }
413 % End
414
415 void __setitem__( const QString &key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
416 % MethodCode
417 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
418 if ( fieldIdx == -1 )
419 {
420 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
421 sipIsErr = 1;
422 }
423 else
424 {
425 if ( a1 == Py_None )
426 {
427 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
428 }
429 else if ( PyBool_Check( a1 ) )
430 {
431 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
432 }
433 else if ( PyLong_Check( a1 ) )
434 {
435 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
436 }
437 else if ( PyFloat_Check( a1 ) )
438 {
439 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
440 }
441 else if ( PyUnicode_Check( a1 ) )
442 {
443 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
444 }
445 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
446 {
447 int state;
448 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
449 if ( !sipIsErr )
450 {
451 sipCpp->setAttribute( fieldIdx, *qvariant );
452 }
453 sipReleaseType( qvariant, sipType_QVariant, state );
454 }
455 else
456 {
457 sipIsErr = 1;
458 }
459 }
460 % End
461
462 void __delitem__( int key ) SIP_HOLDGIL;
463 % MethodCode
464 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
465 sipCpp->deleteAttribute( a0 );
466 else
467 {
468 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
469 sipIsErr = 1;
470 }
471 % End
472
473 void __delitem__( const QString &name ) SIP_HOLDGIL;
474 % MethodCode
475 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
476 if ( fieldIdx == -1 )
477 {
478 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
479 sipIsErr = 1;
480 }
481 else
482 sipCpp->deleteAttribute( fieldIdx );
483 % End
484
485 long __hash__() const SIP_HOLDGIL;
486 % MethodCode
487 sipRes = qHash( *sipCpp );
488 % End
489// clang-format on
490#endif
491
496#ifndef SIP_RUN
497 QgsFeature( QgsFeatureId id = FID_NULL );
498#else
499 QgsFeature( qint64 id = FID_NULL ) SIP_HOLDGIL;
500#endif
501
507#ifndef SIP_RUN
508 QgsFeature( const QgsFields &fields, QgsFeatureId id = FID_NULL );
509#else
510 QgsFeature( const QgsFields &fields, qint64 id = FID_NULL ) SIP_HOLDGIL;
511#endif
512
513 QgsFeature( const QgsFeature &rhs ) SIP_HOLDGIL;
514 QgsFeature &operator=( const QgsFeature &rhs ) SIP_HOLDGIL;
515 bool operator==( const QgsFeature &other ) const SIP_HOLDGIL;
516 bool operator!=( const QgsFeature &other ) const SIP_HOLDGIL;
517
518 virtual ~QgsFeature();
519
524 QgsFeatureId id() const SIP_HOLDGIL;
525
534 void setId( QgsFeatureId id ) SIP_HOLDGIL;
535
552 QgsAttributes attributes() const SIP_HOLDGIL;
553
554#ifndef SIP_RUN
555
565 QVariantMap attributeMap() const;
566#else
567// clang-format off
568
580 SIP_PYOBJECT attributeMap() const SIP_HOLDGIL SIP_TYPEHINT( Dict[str, Optional[object]] );
581 % MethodCode
582 const int fieldSize = sipCpp->fields().size();
583 const int attributeSize = sipCpp->attributeCount();
584 if ( fieldSize == 0 && attributeSize != 0 )
585 {
586 PyErr_SetString( PyExc_ValueError, u"Field definition has not been set for feature"_s.toUtf8().constData() );
587 sipIsErr = 1;
588 }
589 else if ( fieldSize != attributeSize )
590 {
591 PyErr_SetString( PyExc_ValueError, u"Feature attribute size (%1) does not match number of fields (%2)"_s.arg( attributeSize ).arg( fieldSize ).toUtf8().constData() );
592 sipIsErr = 1;
593 }
594 else
595 {
596 QVariantMap *v = new QVariantMap( sipCpp->attributeMap() );
597 const sipTypeDef *qvariantmap_type = sipFindType( "QMap<QString,QVariant>" );
598 sipRes = sipConvertFromNewType( v, qvariantmap_type, Py_None );
599 }
600 % End
601// clang-format on
602#endif
603
608 int attributeCount() const SIP_HOLDGIL;
609
626 void setAttributes( const QgsAttributes &attrs ) SIP_HOLDGIL;
627
628#ifndef SIP_RUN
629
640 Q_INVOKABLE bool setAttribute( int field, const QVariant &attr );
641#else
642// clang-format off
643
668 bool setAttribute( int field, SIP_PYOBJECT attr SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
669 % MethodCode
670 bool rv;
671
672 if ( a1 == Py_None )
673 {
674 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
675 }
676 else if ( PyBool_Check( a1 ) )
677 {
678 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
679 }
680 else if ( PyLong_Check( a1 ) )
681 {
682 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
683 }
684 else if ( PyFloat_Check( a1 ) )
685 {
686 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
687 }
688 else if ( PyUnicode_Check( a1 ) )
689 {
690 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
691 }
692 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
693 {
694 int state;
695 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
696 if ( sipIsErr )
697 {
698 rv = false;
699 }
700 else
701 {
702 rv = sipCpp->setAttribute( a0, *qvariant );
703 }
704 sipReleaseType( qvariant, sipType_QVariant, state );
705 }
706 else
707 {
708 rv = false;
709 }
710
711 if ( !rv )
712 {
713 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
714 sipIsErr = 1;
715 }
716
717 sipRes = rv;
718 % End
719// clang-format on
720#endif
721
731 void initAttributes( int fieldCount ) SIP_HOLDGIL;
732
746 void resizeAttributes( int fieldCount ) SIP_HOLDGIL;
747
754 void padAttributes( int count ) SIP_HOLDGIL;
755
756#ifndef SIP_RUN
757
765 void deleteAttribute( int field );
766#else
767// clang-format off
768
793 void deleteAttribute( int field ) SIP_HOLDGIL;
794 % MethodCode
795 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
796 sipCpp->deleteAttribute( a0 );
797 else
798 {
799 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
800 sipIsErr = 1;
801 }
802 % End
803// clang-format on
804#endif
805
814 bool isValid() const SIP_HOLDGIL;
815
823 void setValid( bool validity ) SIP_HOLDGIL;
824
829 bool hasGeometry() const SIP_HOLDGIL;
830
837 QgsGeometry geometry() const SIP_HOLDGIL;
838
848 void setGeometry( const QgsGeometry &geometry ) SIP_HOLDGIL;
849
880#ifndef SIP_RUN
881 void setGeometry( std::unique_ptr< QgsAbstractGeometry > geometry );
882#else
883// clang-format off
884 void setGeometry( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_HOLDGIL;
885 % MethodCode
886 sipCpp->setGeometry( std::unique_ptr< QgsAbstractGeometry>( a0 ) );
887 % End
888// clang-format on
889#endif
890
896 void clearGeometry() SIP_HOLDGIL;
897
904 void setFields( const QgsFields &fields, bool initAttributes = false SIP_PYARGDEFAULT( true ) ) SIP_HOLDGIL;
905
910 QgsFields fields() const SIP_HOLDGIL;
911
912#ifndef SIP_RUN
913
928 Q_INVOKABLE bool setAttribute( const QString &name, const QVariant &value );
929#else
930// clang-format off
931
958 void setAttribute( const QString &name, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
959 % MethodCode
960 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
961 if ( fieldIdx == -1 )
962 {
963 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
964 sipIsErr = 1;
965 }
966 else
967 {
968 if ( a1 == Py_None )
969 {
970 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
971 }
972 else if ( PyBool_Check( a1 ) )
973 {
974 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
975 }
976 else if ( PyLong_Check( a1 ) )
977 {
978 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
979 }
980 else if ( PyFloat_Check( a1 ) )
981 {
982 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
983 }
984 else if ( PyUnicode_Check( a1 ) )
985 {
986 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
987 }
988 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
989 {
990 int state;
991 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
992 if ( !sipIsErr )
993 {
994 sipCpp->setAttribute( fieldIdx, *qvariant );
995 }
996 sipReleaseType( qvariant, sipType_QVariant, state );
997 }
998 else
999 {
1000 sipIsErr = 1;
1001 }
1002 }
1003 % End
1004// clang-format on
1005#endif
1006
1007#ifndef SIP_RUN
1008
1018 bool deleteAttribute( const QString &name );
1019#else
1020// clang-format off
1021
1051 bool deleteAttribute( const QString &name ) SIP_HOLDGIL;
1052 % MethodCode
1053 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1054 if ( fieldIdx == -1 )
1055 {
1056 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1057 sipIsErr = 1;
1058 sipRes = false;
1059 }
1060 else
1061 {
1062 sipCpp->deleteAttribute( fieldIdx );
1063 sipRes = true;
1064 }
1065 % End
1066// clang-format on
1067#endif
1068
1069#ifndef SIP_RUN
1070
1080 Q_INVOKABLE QVariant attribute( const QString &name ) const;
1081#else
1082// clang-format off
1083
1109 Q_INVOKABLE SIP_PYOBJECT attribute( const QString &name ) const SIP_HOLDGIL;
1110 % MethodCode
1111 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1112 if ( fieldIdx == -1 )
1113 {
1114 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1115 sipIsErr = 1;
1116 }
1117 else
1118 {
1119 QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
1120 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1121 }
1122 % End
1123// clang-format on
1124#endif
1125
1126#ifndef SIP_RUN
1127
1135 QVariant attribute( int fieldIdx ) const;
1136#else
1137// clang-format off
1138
1163 SIP_PYOBJECT attribute( int fieldIdx ) const SIP_HOLDGIL;
1164 % MethodCode
1165 {
1166 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1167 {
1168 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1169 sipIsErr = 1;
1170 }
1171 else
1172 {
1173 QVariant *v = new QVariant( sipCpp->attribute( a0 ) );
1174 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1175 }
1176 }
1177 % End
1178// clang-format on
1179#endif
1180
1181
1182#ifndef SIP_RUN
1183
1190 bool isUnsetValue( int fieldIdx ) const;
1191#else
1192// clang-format off
1193
1201 bool isUnsetValue( int fieldIdx ) const SIP_HOLDGIL;
1202 % MethodCode
1203 {
1204 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1205 {
1206 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1207 sipIsErr = 1;
1208 }
1209 else
1210 {
1211 sipRes = sipCpp->isUnsetValue( a0 );
1212 }
1213 }
1214 % End
1215// clang-format on
1216#endif
1217
1223 const QgsSymbol *embeddedSymbol() const SIP_HOLDGIL;
1224
1232 void setEmbeddedSymbol( QgsSymbol *symbol SIP_TRANSFER ) SIP_HOLDGIL;
1233
1243 int fieldNameIndex( const QString &fieldName ) const SIP_HOLDGIL;
1244
1254 int approximateMemoryUsage() const;
1255
1257 operator QVariant() const
1258 {
1259 return QVariant::fromValue( *this );
1260 }
1261
1262 private:
1263
1264 QExplicitlySharedDataPointer<QgsFeaturePrivate> d;
1265
1266}; // class QgsFeature
1267
1269CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsFeature &feature ) SIP_SKIP;
1271CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsFeature &feature ) SIP_SKIP;
1272
1273// key = feature id, value = changed attributes
1274#ifndef SIP_RUN
1275typedef QMap<QgsFeatureId, QgsAttributeMap> QgsChangedAttributesMap;
1276#else
1277typedef QMap<qint64, QMap<int, QVariant> > QgsChangedAttributesMap;
1278#endif
1279
1280#include "qgsgeometry.h"
1281
1282// key = feature id, value = changed geometry
1283#ifndef SIP_RUN
1284typedef QMap<QgsFeatureId, QgsGeometry> QgsGeometryMap;
1285#else
1286typedef QMap<qint64, QgsGeometry> QgsGeometryMap;
1287#endif
1288
1289typedef QList<QgsFeature> QgsFeatureList;
1290
1291CORE_EXPORT uint qHash( const QgsFeature &key, uint seed = 0 ) SIP_SKIP;
1292
1295
1296#endif
Abstract base class for all geometries.
A vector of attributes.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsAttributes attributes
Definition qgsfeature.h:64
QgsFields fields
Definition qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
QgsFeature(QgsFeatureId id=FID_NULL)
Constructor for QgsFeature.
void setId(QgsFeatureId id)
Sets the feature id for this feature.
QgsGeometry geometry
Definition qgsfeature.h:66
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:46
A geometry is the spatial representation of a feature.
A rectangle specified with double values.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:227
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
uint qHash(const QVariant &variant)
Hash for QVariant.
Definition qgis.cpp:611
#define SIP_TYPEHINT(type)
Definition qgis_sip.h:237
#define SIP_PYARGDEFAULT(value)
Definition qgis_sip.h:153
#define SIP_SKIP
Definition qgis_sip.h:133
#define SIP_TRANSFER
Definition qgis_sip.h:35
#define SIP_HOLDGIL
Definition qgis_sip.h:178
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
CORE_EXPORT uint qHash(const QgsFeature &key, uint seed=0)
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
CORE_EXPORT QDataStream & operator<<(QDataStream &out, const QgsFeature &feature)
Writes the feature to stream out. QGIS version compatibility is not guaranteed.
CORE_EXPORT QDataStream & operator>>(QDataStream &in, QgsFeature &feature)
Reads a feature from stream in into feature. QGIS version compatibility is not guaranteed.
QList< QgsFeature > QgsFeatureList
#define FID_NULL
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
bool operator!=(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)