QGIS API Documentation 4.1.0-Master (60fea48833c)
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#ifdef SIP_RUN
62#if ( SIP_VERSION >= 0x040900 && SIP_VERSION < 0x040c01 )
63#define sipType_QVariant ( ( sipWrapperType * ) sipTypeAsPyTypeObject( sipType_QVariant ) )
64#endif
65#endif
66 Q_GADGET
67
68 Q_PROPERTY( QgsFeatureId id READ id WRITE setId )
70 Q_PROPERTY( QgsFields fields READ fields WRITE setFields )
71 Q_PROPERTY( QgsGeometry geometry READ geometry WRITE setGeometry )
72
73 public:
74#ifdef SIP_RUN
75 // clang-format off
76 SIP_PYOBJECT __iter__() SIP_HOLDGIL;
77 // clang-format on
78 % MethodCode
80 PyObject *attrs = sipConvertFromType( &attributes, sipType_QgsAttributes, Py_None );
81 sipRes = PyObject_GetIter( attrs );
82 // PyObject_GetIter has added a ref to attrs - we need to decrement the ref from sipConvertFromType,
83 // so that the garbage collector will delete attrs when the iterator is deleted
84 Py_DECREF( attrs );
85 % End
86#endif
87
88#ifdef SIP_PYQT5_RUN
89#ifdef SIP_RUN
90// clang-format off
91 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
92 % MethodCode
93 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
94 {
95 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
96 sipIsErr = 1;
97 }
98 else
99 {
100 const QVariant v = sipCpp->attribute( a0 );
101 if ( !v.isValid() )
102 {
103 Py_INCREF( Py_None );
104 sipRes = Py_None;
105 }
106 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
107 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
108 {
109 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
110 PyObject *args = PyTuple_Pack( 1, vartype );
111 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
112 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
113 Py_DECREF( args );
114 Py_DECREF( vartype );
115 }
116 else
117 {
118 switch ( v.userType() )
119 {
120 case QMetaType::Type::Int:
121 sipRes = PyLong_FromLong( v.toInt() );
122 break;
123
124 case QMetaType::Type::UInt:
125 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
126 break;
127
128 case QMetaType::Type::Long:
129 case QMetaType::Type::LongLong:
130 sipRes = PyLong_FromLongLong( v.toLongLong() );
131 break;
132
133 case QMetaType::Type::ULong:
134 case QMetaType::Type::ULongLong:
135 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
136 break;
137
138 case QMetaType::Type::Bool:
139 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
140 break;
141
142 case QMetaType::Type::Float:
143 case QMetaType::Type::Double:
144 sipRes = PyFloat_FromDouble( v.toDouble() );
145 break;
146
147 case QMetaType::Type::QString:
148 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
149 break;
150
151 default:
152 {
153 QVariant *newV = new QVariant( v );
154 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
155 break;
156 }
157 }
158 }
159 }
160 % End
161
162 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
163 % MethodCode
164 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
165 if ( fieldIdx == -1 )
166 {
167 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
168 sipIsErr = 1;
169 }
170 else
171 {
172 const QVariant v = sipCpp->attribute( fieldIdx );
173 if ( !v.isValid() )
174 {
175 Py_INCREF( Py_None );
176 sipRes = Py_None;
177 }
178 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
179 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
180 {
181 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
182 PyObject *args = PyTuple_Pack( 1, vartype );
183 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
184 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
185 Py_DECREF( args );
186 Py_DECREF( vartype );
187 }
188 else
189 {
190 switch ( v.userType() )
191 {
192 case QMetaType::Type::Int:
193 sipRes = PyLong_FromLong( v.toInt() );
194 break;
195
196 case QMetaType::Type::UInt:
197 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
198 break;
199
200 case QMetaType::Type::Long:
201 case QMetaType::Type::LongLong:
202 sipRes = PyLong_FromLongLong( v.toLongLong() );
203 break;
204
205 case QMetaType::Type::ULong:
206 case QMetaType::Type::ULongLong:
207 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
208 break;
209
210 case QMetaType::Type::Bool:
211 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
212 break;
213
214 case QMetaType::Type::Float:
215 case QMetaType::Type::Double:
216 sipRes = PyFloat_FromDouble( v.toDouble() );
217 break;
218
219 case QMetaType::Type::QString:
220 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
221 break;
222
223 default:
224 {
225 QVariant *newV = new QVariant( v );
226 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
227 break;
228 }
229 }
230 }
231 }
232 % End
233// clang-format on
234#endif
235#endif
236
237#ifdef SIP_PYQT6_RUN
238#ifdef SIP_RUN
239// clang-format off
240 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
241 % MethodCode
242 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
243 {
244 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
245 sipIsErr = 1;
246 }
247 else
248 {
249 const QVariant v = sipCpp->attribute( a0 );
250 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
251 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
252 {
253 Py_INCREF( Py_None );
254 sipRes = Py_None;
255 }
256 else
257 {
258 switch ( v.userType() )
259 {
260 case QMetaType::Type::Int:
261 sipRes = PyLong_FromLong( v.toInt() );
262 break;
263
264 case QMetaType::Type::UInt:
265 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
266 break;
267
268 case QMetaType::Type::Long:
269 case QMetaType::Type::LongLong:
270 sipRes = PyLong_FromLongLong( v.toLongLong() );
271 break;
272
273 case QMetaType::Type::ULong:
274 case QMetaType::Type::ULongLong:
275 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
276 break;
277
278 case QMetaType::Type::Bool:
279 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
280 break;
281
282 case QMetaType::Type::Float:
283 case QMetaType::Type::Double:
284 sipRes = PyFloat_FromDouble( v.toDouble() );
285 break;
286
287 case QMetaType::Type::QString:
288 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
289 break;
290
291 default:
292 {
293 QVariant *newV = new QVariant( v );
294 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
295 break;
296 }
297 }
298 }
299 }
300 % End
301
302 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
303 % MethodCode
304 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
305 if ( fieldIdx == -1 )
306 {
307 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
308 sipIsErr = 1;
309 }
310 else
311 {
312 const QVariant v = sipCpp->attribute( fieldIdx );
313 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
314 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
315 {
316 Py_INCREF( Py_None );
317 sipRes = Py_None;
318 }
319 else
320 {
321 switch ( v.userType() )
322 {
323 case QMetaType::Type::Int:
324 sipRes = PyLong_FromLong( v.toInt() );
325 break;
326
327 case QMetaType::Type::UInt:
328 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
329 break;
330
331 case QMetaType::Type::Long:
332 case QMetaType::Type::LongLong:
333 sipRes = PyLong_FromLongLong( v.toLongLong() );
334 break;
335
336 case QMetaType::Type::ULong:
337 case QMetaType::Type::ULongLong:
338 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
339 break;
340
341 case QMetaType::Type::Bool:
342 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
343 break;
344
345 case QMetaType::Type::Float:
346 case QMetaType::Type::Double:
347 sipRes = PyFloat_FromDouble( v.toDouble() );
348 break;
349
350 case QMetaType::Type::QString:
351 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
352 break;
353
354 default:
355 {
356 QVariant *newV = new QVariant( v );
357 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
358 break;
359 }
360 }
361 }
362 }
363 % End
364// clang-format on
365#endif
366#endif
367
368#ifdef SIP_RUN
369// clang-format off
370 void __setitem__( int key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
371 % MethodCode
372 bool rv;
373
374 if ( a1 == Py_None )
375 {
376 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
377 }
378 else if ( PyBool_Check( a1 ) )
379 {
380 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
381 }
382 else if ( PyLong_Check( a1 ) )
383 {
384 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
385 }
386 else if ( PyFloat_Check( a1 ) )
387 {
388 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
389 }
390 else if ( PyUnicode_Check( a1 ) )
391 {
392 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
393 }
394 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
395 {
396 int state;
397 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
398 if ( sipIsErr )
399 {
400 rv = false;
401 }
402 else
403 {
404 rv = sipCpp->setAttribute( a0, *qvariant );
405 }
406 sipReleaseType( qvariant, sipType_QVariant, state );
407 }
408 else
409 {
410 rv = false;
411 }
412
413 if ( !rv )
414 {
415 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
416 sipIsErr = 1;
417 }
418 % End
419
420 void __setitem__( const QString &key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
421 % MethodCode
422 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
423 if ( fieldIdx == -1 )
424 {
425 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
426 sipIsErr = 1;
427 }
428 else
429 {
430 if ( a1 == Py_None )
431 {
432 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
433 }
434 else if ( PyBool_Check( a1 ) )
435 {
436 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
437 }
438 else if ( PyLong_Check( a1 ) )
439 {
440 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
441 }
442 else if ( PyFloat_Check( a1 ) )
443 {
444 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
445 }
446 else if ( PyUnicode_Check( a1 ) )
447 {
448 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
449 }
450 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
451 {
452 int state;
453 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
454 if ( !sipIsErr )
455 {
456 sipCpp->setAttribute( fieldIdx, *qvariant );
457 }
458 sipReleaseType( qvariant, sipType_QVariant, state );
459 }
460 else
461 {
462 sipIsErr = 1;
463 }
464 }
465 % End
466
467 void __delitem__( int key ) SIP_HOLDGIL;
468 % MethodCode
469 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
470 sipCpp->deleteAttribute( a0 );
471 else
472 {
473 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
474 sipIsErr = 1;
475 }
476 % End
477
478 void __delitem__( const QString &name ) SIP_HOLDGIL;
479 % MethodCode
480 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
481 if ( fieldIdx == -1 )
482 {
483 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
484 sipIsErr = 1;
485 }
486 else
487 sipCpp->deleteAttribute( fieldIdx );
488 % End
489
490 long __hash__() const SIP_HOLDGIL;
491 % MethodCode
492 sipRes = qHash( *sipCpp );
493 % End
494// clang-format on
495#endif
496
501#ifndef SIP_RUN
502 QgsFeature( QgsFeatureId id = FID_NULL );
503#else
504 QgsFeature( qint64 id = FID_NULL ) SIP_HOLDGIL;
505#endif
506
512#ifndef SIP_RUN
513 QgsFeature( const QgsFields &fields, QgsFeatureId id = FID_NULL );
514#else
515 QgsFeature( const QgsFields &fields, qint64 id = FID_NULL ) SIP_HOLDGIL;
516#endif
517
518 QgsFeature( const QgsFeature &rhs ) SIP_HOLDGIL;
519 QgsFeature &operator=( const QgsFeature &rhs ) SIP_HOLDGIL;
520 bool operator==( const QgsFeature &other ) const SIP_HOLDGIL;
521 bool operator!=( const QgsFeature &other ) const SIP_HOLDGIL;
522
523 virtual ~QgsFeature();
524
529 QgsFeatureId id() const SIP_HOLDGIL;
530
539 void setId( QgsFeatureId id ) SIP_HOLDGIL;
540
557 QgsAttributes attributes() const SIP_HOLDGIL;
558
559#ifndef SIP_RUN
560
570 QVariantMap attributeMap() const;
571#else
572// clang-format off
573
585 SIP_PYOBJECT attributeMap() const SIP_HOLDGIL SIP_TYPEHINT( Dict[str, Optional[object]] );
586 % MethodCode
587 const int fieldSize = sipCpp->fields().size();
588 const int attributeSize = sipCpp->attributeCount();
589 if ( fieldSize == 0 && attributeSize != 0 )
590 {
591 PyErr_SetString( PyExc_ValueError, u"Field definition has not been set for feature"_s.toUtf8().constData() );
592 sipIsErr = 1;
593 }
594 else if ( fieldSize != attributeSize )
595 {
596 PyErr_SetString( PyExc_ValueError, u"Feature attribute size (%1) does not match number of fields (%2)"_s.arg( attributeSize ).arg( fieldSize ).toUtf8().constData() );
597 sipIsErr = 1;
598 }
599 else
600 {
601 QVariantMap *v = new QVariantMap( sipCpp->attributeMap() );
602 const sipTypeDef *qvariantmap_type = sipFindType( "QMap<QString,QVariant>" );
603 sipRes = sipConvertFromNewType( v, qvariantmap_type, Py_None );
604 }
605 % End
606// clang-format on
607#endif
608
613 int attributeCount() const SIP_HOLDGIL;
614
631 void setAttributes( const QgsAttributes &attrs ) SIP_HOLDGIL;
632
633#ifndef SIP_RUN
634
645 Q_INVOKABLE bool setAttribute( int field, const QVariant &attr );
646#else
647// clang-format off
648
673 bool setAttribute( int field, SIP_PYOBJECT attr SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
674 % MethodCode
675 bool rv;
676
677 if ( a1 == Py_None )
678 {
679 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
680 }
681 else if ( PyBool_Check( a1 ) )
682 {
683 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
684 }
685 else if ( PyLong_Check( a1 ) )
686 {
687 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
688 }
689 else if ( PyFloat_Check( a1 ) )
690 {
691 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
692 }
693 else if ( PyUnicode_Check( a1 ) )
694 {
695 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
696 }
697 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
698 {
699 int state;
700 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
701 if ( sipIsErr )
702 {
703 rv = false;
704 }
705 else
706 {
707 rv = sipCpp->setAttribute( a0, *qvariant );
708 }
709 sipReleaseType( qvariant, sipType_QVariant, state );
710 }
711 else
712 {
713 rv = false;
714 }
715
716 if ( !rv )
717 {
718 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
719 sipIsErr = 1;
720 }
721
722 sipRes = rv;
723 % End
724// clang-format on
725#endif
726
736 void initAttributes( int fieldCount ) SIP_HOLDGIL;
737
751 void resizeAttributes( int fieldCount ) SIP_HOLDGIL;
752
759 void padAttributes( int count ) SIP_HOLDGIL;
760
761#ifndef SIP_RUN
762
770 void deleteAttribute( int field );
771#else
772// clang-format off
773
798 void deleteAttribute( int field ) SIP_HOLDGIL;
799 % MethodCode
800 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
801 sipCpp->deleteAttribute( a0 );
802 else
803 {
804 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
805 sipIsErr = 1;
806 }
807 % End
808// clang-format on
809#endif
810
819 bool isValid() const SIP_HOLDGIL;
820
828 void setValid( bool validity ) SIP_HOLDGIL;
829
834 bool hasGeometry() const SIP_HOLDGIL;
835
842 QgsGeometry geometry() const SIP_HOLDGIL;
843
853 void setGeometry( const QgsGeometry &geometry ) SIP_HOLDGIL;
854
885#ifndef SIP_RUN
886 void setGeometry( std::unique_ptr< QgsAbstractGeometry > geometry );
887#else
888// clang-format off
889 void setGeometry( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_HOLDGIL;
890 % MethodCode
891 sipCpp->setGeometry( std::unique_ptr< QgsAbstractGeometry>( a0 ) );
892 % End
893// clang-format on
894#endif
895
901 void clearGeometry() SIP_HOLDGIL;
902
909 void setFields( const QgsFields &fields, bool initAttributes = false SIP_PYARGDEFAULT( true ) ) SIP_HOLDGIL;
910
915 QgsFields fields() const SIP_HOLDGIL;
916
917#ifndef SIP_RUN
918
933 Q_INVOKABLE bool setAttribute( const QString &name, const QVariant &value );
934#else
935// clang-format off
936
963 void setAttribute( const QString &name, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
964 % MethodCode
965 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
966 if ( fieldIdx == -1 )
967 {
968 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
969 sipIsErr = 1;
970 }
971 else
972 {
973 if ( a1 == Py_None )
974 {
975 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
976 }
977 else if ( PyBool_Check( a1 ) )
978 {
979 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
980 }
981 else if ( PyLong_Check( a1 ) )
982 {
983 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
984 }
985 else if ( PyFloat_Check( a1 ) )
986 {
987 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
988 }
989 else if ( PyUnicode_Check( a1 ) )
990 {
991 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
992 }
993 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
994 {
995 int state;
996 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
997 if ( !sipIsErr )
998 {
999 sipCpp->setAttribute( fieldIdx, *qvariant );
1000 }
1001 sipReleaseType( qvariant, sipType_QVariant, state );
1002 }
1003 else
1004 {
1005 sipIsErr = 1;
1006 }
1007 }
1008 % End
1009// clang-format on
1010#endif
1011
1012#ifndef SIP_RUN
1013
1023 bool deleteAttribute( const QString &name );
1024#else
1025// clang-format off
1026
1056 bool deleteAttribute( const QString &name ) SIP_HOLDGIL;
1057 % MethodCode
1058 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1059 if ( fieldIdx == -1 )
1060 {
1061 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1062 sipIsErr = 1;
1063 sipRes = false;
1064 }
1065 else
1066 {
1067 sipCpp->deleteAttribute( fieldIdx );
1068 sipRes = true;
1069 }
1070 % End
1071// clang-format on
1072#endif
1073
1074#ifndef SIP_RUN
1075
1085 Q_INVOKABLE QVariant attribute( const QString &name ) const;
1086#else
1087// clang-format off
1088
1114 Q_INVOKABLE SIP_PYOBJECT attribute( const QString &name ) const SIP_HOLDGIL;
1115 % MethodCode
1116 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1117 if ( fieldIdx == -1 )
1118 {
1119 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1120 sipIsErr = 1;
1121 }
1122 else
1123 {
1124 QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
1125 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1126 }
1127 % End
1128// clang-format on
1129#endif
1130
1131#ifndef SIP_RUN
1132
1140 QVariant attribute( int fieldIdx ) const;
1141#else
1142// clang-format off
1143
1168 SIP_PYOBJECT attribute( int fieldIdx ) const SIP_HOLDGIL;
1169 % MethodCode
1170 {
1171 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1172 {
1173 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1174 sipIsErr = 1;
1175 }
1176 else
1177 {
1178 QVariant *v = new QVariant( sipCpp->attribute( a0 ) );
1179 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1180 }
1181 }
1182 % End
1183// clang-format on
1184#endif
1185
1186
1187#ifndef SIP_RUN
1188
1195 bool isUnsetValue( int fieldIdx ) const;
1196#else
1197// clang-format off
1198
1206 bool isUnsetValue( int fieldIdx ) const SIP_HOLDGIL;
1207 % MethodCode
1208 {
1209 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1210 {
1211 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1212 sipIsErr = 1;
1213 }
1214 else
1215 {
1216 sipRes = sipCpp->isUnsetValue( a0 );
1217 }
1218 }
1219 % End
1220// clang-format on
1221#endif
1222
1228 const QgsSymbol *embeddedSymbol() const SIP_HOLDGIL;
1229
1237 void setEmbeddedSymbol( QgsSymbol *symbol SIP_TRANSFER ) SIP_HOLDGIL;
1238
1248 int fieldNameIndex( const QString &fieldName ) const SIP_HOLDGIL;
1249
1259 int approximateMemoryUsage() const;
1260
1262 operator QVariant() const
1263 {
1264 return QVariant::fromValue( *this );
1265 }
1266
1267 private:
1268
1269 QExplicitlySharedDataPointer<QgsFeaturePrivate> d;
1270
1271}; // class QgsFeature
1272
1274CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsFeature &feature ) SIP_SKIP;
1276CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsFeature &feature ) SIP_SKIP;
1277
1278// key = feature id, value = changed attributes
1279#ifndef SIP_RUN
1280typedef QMap<QgsFeatureId, QgsAttributeMap> QgsChangedAttributesMap;
1281#else
1282typedef QMap<qint64, QMap<int, QVariant> > QgsChangedAttributesMap;
1283#endif
1284
1285#include "qgsgeometry.h"
1286
1287// key = feature id, value = changed geometry
1288#ifndef SIP_RUN
1289typedef QMap<QgsFeatureId, QgsGeometry> QgsGeometryMap;
1290#else
1291typedef QMap<qint64, QgsGeometry> QgsGeometryMap;
1292#endif
1293
1294typedef QList<QgsFeature> QgsFeatureList;
1295
1296CORE_EXPORT uint qHash( const QgsFeature &key, uint seed = 0 ) SIP_SKIP;
1297
1300
1301#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:69
QgsFields fields
Definition qgsfeature.h:70
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:71
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:239
#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)