QGIS API Documentation 3.99.0-Master (d270888f95f)
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
75#ifdef SIP_RUN
76 SIP_PYOBJECT __iter__() SIP_HOLDGIL;
77 % MethodCode
79 PyObject *attrs = sipConvertFromType( &attributes, sipType_QgsAttributes, Py_None );
80 sipRes = PyObject_GetIter( attrs );
81 // PyObject_GetIter has added a ref to attrs - we need to decrement the ref from sipConvertFromType,
82 // so that the garbage collector will delete attrs when the iterator is deleted
83 Py_DECREF( attrs );
84 % End
85#endif
86
87#ifdef SIP_PYQT5_RUN
88#ifdef SIP_RUN
89 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
90 % MethodCode
91 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
92 {
93 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
94 sipIsErr = 1;
95 }
96 else
97 {
98 const QVariant v = sipCpp->attribute( a0 );
99 if ( !v.isValid() )
100 {
101 Py_INCREF( Py_None );
102 sipRes = Py_None;
103 }
104 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
105 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
106 {
107 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
108 PyObject *args = PyTuple_Pack( 1, vartype );
109 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
110 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
111 Py_DECREF( args );
112 Py_DECREF( vartype );
113 }
114 else
115 {
116 switch ( v.userType() )
117 {
118 case QMetaType::Type::Int:
119 sipRes = PyLong_FromLong( v.toInt() );
120 break;
121
122 case QMetaType::Type::UInt:
123 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
124 break;
125
126 case QMetaType::Type::Long:
127 case QMetaType::Type::LongLong:
128 sipRes = PyLong_FromLongLong( v.toLongLong() );
129 break;
130
131 case QMetaType::Type::ULong:
132 case QMetaType::Type::ULongLong:
133 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
134 break;
135
136 case QMetaType::Type::Bool:
137 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
138 break;
139
140 case QMetaType::Type::Float:
141 case QMetaType::Type::Double:
142 sipRes = PyFloat_FromDouble( v.toDouble() );
143 break;
144
145 case QMetaType::Type::QString:
146 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
147 break;
148
149 default:
150 {
151 QVariant *newV = new QVariant( v );
152 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
153 break;
154 }
155 }
156 }
157 }
158 % End
159
160 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
161 % MethodCode
162 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
163 if ( fieldIdx == -1 )
164 {
165 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
166 sipIsErr = 1;
167 }
168 else
169 {
170 const QVariant v = sipCpp->attribute( fieldIdx );
171 if ( !v.isValid() )
172 {
173 Py_INCREF( Py_None );
174 sipRes = Py_None;
175 }
176 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
177 else if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
178 {
179 PyObject *vartype = sipConvertFromEnum( v.type(), sipType_QVariant_Type );
180 PyObject *args = PyTuple_Pack( 1, vartype );
181 PyTypeObject *typeObj = sipTypeAsPyTypeObject( sipType_QVariant );
182 sipRes = PyObject_Call( ( PyObject * )typeObj, args, nullptr );
183 Py_DECREF( args );
184 Py_DECREF( vartype );
185 }
186 else
187 {
188 switch ( v.userType() )
189 {
190 case QMetaType::Type::Int:
191 sipRes = PyLong_FromLong( v.toInt() );
192 break;
193
194 case QMetaType::Type::UInt:
195 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
196 break;
197
198 case QMetaType::Type::Long:
199 case QMetaType::Type::LongLong:
200 sipRes = PyLong_FromLongLong( v.toLongLong() );
201 break;
202
203 case QMetaType::Type::ULong:
204 case QMetaType::Type::ULongLong:
205 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
206 break;
207
208 case QMetaType::Type::Bool:
209 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
210 break;
211
212 case QMetaType::Type::Float:
213 case QMetaType::Type::Double:
214 sipRes = PyFloat_FromDouble( v.toDouble() );
215 break;
216
217 case QMetaType::Type::QString:
218 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
219 break;
220
221 default:
222 {
223 QVariant *newV = new QVariant( v );
224 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
225 break;
226 }
227 }
228 }
229 }
230 % End
231#endif
232#endif
233
234#ifdef SIP_PYQT6_RUN
235#ifdef SIP_RUN
236 SIP_PYOBJECT __getitem__( int key ) SIP_HOLDGIL;
237 % MethodCode
238 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
239 {
240 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
241 sipIsErr = 1;
242 }
243 else
244 {
245 const QVariant v = sipCpp->attribute( a0 );
246 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
247 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
248 {
249 Py_INCREF( Py_None );
250 sipRes = Py_None;
251 }
252 else
253 {
254 switch ( v.userType() )
255 {
256 case QMetaType::Type::Int:
257 sipRes = PyLong_FromLong( v.toInt() );
258 break;
259
260 case QMetaType::Type::UInt:
261 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
262 break;
263
264 case QMetaType::Type::Long:
265 case QMetaType::Type::LongLong:
266 sipRes = PyLong_FromLongLong( v.toLongLong() );
267 break;
268
269 case QMetaType::Type::ULong:
270 case QMetaType::Type::ULongLong:
271 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
272 break;
273
274 case QMetaType::Type::Bool:
275 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
276 break;
277
278 case QMetaType::Type::Float:
279 case QMetaType::Type::Double:
280 sipRes = PyFloat_FromDouble( v.toDouble() );
281 break;
282
283 case QMetaType::Type::QString:
284 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
285 break;
286
287 default:
288 {
289 QVariant *newV = new QVariant( v );
290 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
291 break;
292 }
293 }
294 }
295 }
296 % End
297
298 SIP_PYOBJECT __getitem__( const QString &name ) SIP_HOLDGIL;
299 % MethodCode
300 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
301 if ( fieldIdx == -1 )
302 {
303 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
304 sipIsErr = 1;
305 }
306 else
307 {
308 const QVariant v = sipCpp->attribute( fieldIdx );
309 // QByteArray null handling is "special"! See null_from_qvariant_converter in conversions.sip
310 if ( QgsVariantUtils::isNull( v, true ) && v.userType() != QMetaType::Type::QByteArray )
311 {
312 Py_INCREF( Py_None );
313 sipRes = Py_None;
314 }
315 else
316 {
317 switch ( v.userType() )
318 {
319 case QMetaType::Type::Int:
320 sipRes = PyLong_FromLong( v.toInt() );
321 break;
322
323 case QMetaType::Type::UInt:
324 sipRes = PyLong_FromUnsignedLong( v.toUInt() );
325 break;
326
327 case QMetaType::Type::Long:
328 case QMetaType::Type::LongLong:
329 sipRes = PyLong_FromLongLong( v.toLongLong() );
330 break;
331
332 case QMetaType::Type::ULong:
333 case QMetaType::Type::ULongLong:
334 sipRes = PyLong_FromUnsignedLongLong( v.toULongLong() );
335 break;
336
337 case QMetaType::Type::Bool:
338 sipRes = PyBool_FromLong( v.toBool() ? 1 : 0 );
339 break;
340
341 case QMetaType::Type::Float:
342 case QMetaType::Type::Double:
343 sipRes = PyFloat_FromDouble( v.toDouble() );
344 break;
345
346 case QMetaType::Type::QString:
347 sipRes = PyUnicode_FromString( v.toString().toUtf8().constData() );
348 break;
349
350 default:
351 {
352 QVariant *newV = new QVariant( v );
353 sipRes = sipConvertFromNewType( newV, sipType_QVariant, Py_None );
354 break;
355 }
356 }
357 }
358 }
359 % End
360#endif
361#endif
362
363#ifdef SIP_RUN
364 void __setitem__( int key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
365 % MethodCode
366 bool rv;
367
368 if ( a1 == Py_None )
369 {
370 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
371 }
372 else if ( PyBool_Check( a1 ) )
373 {
374 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
375 }
376 else if ( PyLong_Check( a1 ) )
377 {
378 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
379 }
380 else if ( PyFloat_Check( a1 ) )
381 {
382 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
383 }
384 else if ( PyUnicode_Check( a1 ) )
385 {
386 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
387 }
388 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
389 {
390 int state;
391 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
392 if ( sipIsErr )
393 {
394 rv = false;
395 }
396 else
397 {
398 rv = sipCpp->setAttribute( a0, *qvariant );
399 }
400 sipReleaseType( qvariant, sipType_QVariant, state );
401 }
402 else
403 {
404 rv = false;
405 }
406
407 if ( !rv )
408 {
409 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
410 sipIsErr = 1;
411 }
412 % End
413
414 void __setitem__( const QString &key, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
415 % MethodCode
416 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
417 if ( fieldIdx == -1 )
418 {
419 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
420 sipIsErr = 1;
421 }
422 else
423 {
424 if ( a1 == Py_None )
425 {
426 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
427 }
428 else if ( PyBool_Check( a1 ) )
429 {
430 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
431 }
432 else if ( PyLong_Check( a1 ) )
433 {
434 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
435 }
436 else if ( PyFloat_Check( a1 ) )
437 {
438 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
439 }
440 else if ( PyUnicode_Check( a1 ) )
441 {
442 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
443 }
444 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
445 {
446 int state;
447 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
448 if ( !sipIsErr )
449 {
450 sipCpp->setAttribute( fieldIdx, *qvariant );
451 }
452 sipReleaseType( qvariant, sipType_QVariant, state );
453 }
454 else
455 {
456 sipIsErr = 1;
457 }
458 }
459 % End
460
461 void __delitem__( int key ) SIP_HOLDGIL;
462 % MethodCode
463 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
464 sipCpp->deleteAttribute( a0 );
465 else
466 {
467 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
468 sipIsErr = 1;
469 }
470 % End
471
472 void __delitem__( const QString &name ) SIP_HOLDGIL;
473 % MethodCode
474 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
475 if ( fieldIdx == -1 )
476 {
477 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
478 sipIsErr = 1;
479 }
480 else
481 sipCpp->deleteAttribute( fieldIdx );
482 % End
483
484 long __hash__() const SIP_HOLDGIL;
485 % MethodCode
486 sipRes = qHash( *sipCpp );
487 % End
488#endif
489
494#ifndef SIP_RUN
495 QgsFeature( QgsFeatureId id = FID_NULL );
496#else
497 QgsFeature( qint64 id = FID_NULL ) SIP_HOLDGIL;
498#endif
499
505#ifndef SIP_RUN
506 QgsFeature( const QgsFields &fields, QgsFeatureId id = FID_NULL );
507#else
508 QgsFeature( const QgsFields &fields, qint64 id = FID_NULL ) SIP_HOLDGIL;
509#endif
510
511 QgsFeature( const QgsFeature &rhs ) SIP_HOLDGIL;
512 QgsFeature &operator=( const QgsFeature &rhs ) SIP_HOLDGIL;
513 bool operator==( const QgsFeature &other ) const SIP_HOLDGIL;
514 bool operator!=( const QgsFeature &other ) const SIP_HOLDGIL;
515
516 virtual ~QgsFeature();
517
522 QgsFeatureId id() const SIP_HOLDGIL;
523
532 void setId( QgsFeatureId id ) SIP_HOLDGIL;
533
550 QgsAttributes attributes() const SIP_HOLDGIL;
551
552#ifndef SIP_RUN
553
563 QVariantMap attributeMap() const;
564#else
565
577 SIP_PYOBJECT attributeMap() const SIP_HOLDGIL SIP_TYPEHINT( Dict[str, Optional[object]] );
578 % MethodCode
579 const int fieldSize = sipCpp->fields().size();
580 const int attributeSize = sipCpp->attributeCount();
581 if ( fieldSize == 0 && attributeSize != 0 )
582 {
583 PyErr_SetString( PyExc_ValueError, u"Field definition has not been set for feature"_s.toUtf8().constData() );
584 sipIsErr = 1;
585 }
586 else if ( fieldSize != attributeSize )
587 {
588 PyErr_SetString( PyExc_ValueError, u"Feature attribute size (%1) does not match number of fields (%2)"_s.arg( attributeSize ).arg( fieldSize ).toUtf8().constData() );
589 sipIsErr = 1;
590 }
591 else
592 {
593 QVariantMap *v = new QVariantMap( sipCpp->attributeMap() );
594 const sipTypeDef *qvariantmap_type = sipFindType( "QMap<QString,QVariant>" );
595 sipRes = sipConvertFromNewType( v, qvariantmap_type, Py_None );
596 }
597 % End
598#endif
599
604 int attributeCount() const SIP_HOLDGIL;
605
622 void setAttributes( const QgsAttributes &attrs ) SIP_HOLDGIL;
623
624#ifndef SIP_RUN
625
636 Q_INVOKABLE bool setAttribute( int field, const QVariant &attr );
637#else
638
663 bool setAttribute( int field, SIP_PYOBJECT attr SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
664 % MethodCode
665 bool rv;
666
667 if ( a1 == Py_None )
668 {
669 rv = sipCpp->setAttribute( a0, QVariant( QVariant::Int ) );
670 }
671 else if ( PyBool_Check( a1 ) )
672 {
673 rv = sipCpp->setAttribute( a0, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
674 }
675 else if ( PyLong_Check( a1 ) )
676 {
677 rv = sipCpp->setAttribute( a0, QVariant( PyLong_AsLongLong( a1 ) ) );
678 }
679 else if ( PyFloat_Check( a1 ) )
680 {
681 rv = sipCpp->setAttribute( a0, QVariant( PyFloat_AsDouble( a1 ) ) );
682 }
683 else if ( PyUnicode_Check( a1 ) )
684 {
685 rv = sipCpp->setAttribute( a0, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
686 }
687 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
688 {
689 int state;
690 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
691 if ( sipIsErr )
692 {
693 rv = false;
694 }
695 else
696 {
697 rv = sipCpp->setAttribute( a0, *qvariant );
698 }
699 sipReleaseType( qvariant, sipType_QVariant, state );
700 }
701 else
702 {
703 rv = false;
704 }
705
706 if ( !rv )
707 {
708 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
709 sipIsErr = 1;
710 }
711
712 sipRes = rv;
713 % End
714#endif
715
725 void initAttributes( int fieldCount ) SIP_HOLDGIL;
726
740 void resizeAttributes( int fieldCount ) SIP_HOLDGIL;
741
748 void padAttributes( int count ) SIP_HOLDGIL;
749
750#ifndef SIP_RUN
751
759 void deleteAttribute( int field );
760#else
761
786 void deleteAttribute( int field ) SIP_HOLDGIL;
787 % MethodCode
788 if ( a0 >= 0 && a0 < sipCpp->attributeCount() )
789 sipCpp->deleteAttribute( a0 );
790 else
791 {
792 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
793 sipIsErr = 1;
794 }
795 % End
796#endif
797
806 bool isValid() const SIP_HOLDGIL;
807
815 void setValid( bool validity ) SIP_HOLDGIL;
816
821 bool hasGeometry() const SIP_HOLDGIL;
822
829 QgsGeometry geometry() const SIP_HOLDGIL;
830
840 void setGeometry( const QgsGeometry &geometry ) SIP_HOLDGIL;
841
872#ifndef SIP_RUN
873 void setGeometry( std::unique_ptr< QgsAbstractGeometry > geometry );
874#else
875 void setGeometry( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_HOLDGIL;
876 % MethodCode
877 sipCpp->setGeometry( std::unique_ptr< QgsAbstractGeometry>( a0 ) );
878 % End
879#endif
880
886 void clearGeometry() SIP_HOLDGIL;
887
894 void setFields( const QgsFields &fields, bool initAttributes = false SIP_PYARGDEFAULT( true ) ) SIP_HOLDGIL;
895
900 QgsFields fields() const SIP_HOLDGIL;
901
902#ifndef SIP_RUN
903
918 Q_INVOKABLE bool setAttribute( const QString &name, const QVariant &value );
919#else
920
947 void setAttribute( const QString &name, SIP_PYOBJECT value SIP_TYPEHINT( Optional[Union[bool, int, float, str, QVariant]] ) ) SIP_HOLDGIL;
948 % MethodCode
949 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
950 if ( fieldIdx == -1 )
951 {
952 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
953 sipIsErr = 1;
954 }
955 else
956 {
957 if ( a1 == Py_None )
958 {
959 sipCpp->setAttribute( fieldIdx, QVariant( QVariant::Int ) );
960 }
961 else if ( PyBool_Check( a1 ) )
962 {
963 sipCpp->setAttribute( fieldIdx, QVariant( PyObject_IsTrue( a1 ) == 1 ) );
964 }
965 else if ( PyLong_Check( a1 ) )
966 {
967 sipCpp->setAttribute( fieldIdx, QVariant( PyLong_AsLongLong( a1 ) ) );
968 }
969 else if ( PyFloat_Check( a1 ) )
970 {
971 sipCpp->setAttribute( fieldIdx, QVariant( PyFloat_AsDouble( a1 ) ) );
972 }
973 else if ( PyUnicode_Check( a1 ) )
974 {
975 sipCpp->setAttribute( fieldIdx, QVariant( QString::fromUtf8( PyUnicode_AsUTF8( a1 ) ) ) );
976 }
977 else if ( sipCanConvertToType( a1, sipType_QVariant, SIP_NOT_NONE ) )
978 {
979 int state;
980 QVariant *qvariant = reinterpret_cast<QVariant *>( sipConvertToType( a1, sipType_QVariant, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
981 if ( !sipIsErr )
982 {
983 sipCpp->setAttribute( fieldIdx, *qvariant );
984 }
985 sipReleaseType( qvariant, sipType_QVariant, state );
986 }
987 else
988 {
989 sipIsErr = 1;
990 }
991 }
992 % End
993#endif
994
995#ifndef SIP_RUN
996
1006 bool deleteAttribute( const QString &name );
1007#else
1008
1038 bool deleteAttribute( const QString &name ) SIP_HOLDGIL;
1039 % MethodCode
1040 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1041 if ( fieldIdx == -1 )
1042 {
1043 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1044 sipIsErr = 1;
1045 sipRes = false;
1046 }
1047 else
1048 {
1049 sipCpp->deleteAttribute( fieldIdx );
1050 sipRes = true;
1051 }
1052 % End
1053#endif
1054
1055#ifndef SIP_RUN
1056
1066 Q_INVOKABLE QVariant attribute( const QString &name ) const;
1067#else
1068
1094 Q_INVOKABLE SIP_PYOBJECT attribute( const QString &name ) const SIP_HOLDGIL;
1095 % MethodCode
1096 int fieldIdx = sipCpp->fieldNameIndex( *a0 );
1097 if ( fieldIdx == -1 )
1098 {
1099 PyErr_SetString( PyExc_KeyError, a0->toLatin1() );
1100 sipIsErr = 1;
1101 }
1102 else
1103 {
1104 QVariant *v = new QVariant( sipCpp->attribute( fieldIdx ) );
1105 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1106 }
1107 % End
1108#endif
1109
1110#ifndef SIP_RUN
1111
1119 QVariant attribute( int fieldIdx ) const;
1120#else
1121
1146 SIP_PYOBJECT attribute( int fieldIdx ) const SIP_HOLDGIL;
1147 % MethodCode
1148 {
1149 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1150 {
1151 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1152 sipIsErr = 1;
1153 }
1154 else
1155 {
1156 QVariant *v = new QVariant( sipCpp->attribute( a0 ) );
1157 sipRes = sipConvertFromNewType( v, sipType_QVariant, Py_None );
1158 }
1159 }
1160 % End
1161#endif
1162
1163
1164#ifndef SIP_RUN
1165
1172 bool isUnsetValue( int fieldIdx ) const;
1173#else
1174
1182 bool isUnsetValue( int fieldIdx ) const SIP_HOLDGIL;
1183 % MethodCode
1184 {
1185 if ( a0 < 0 || a0 >= sipCpp->attributeCount() )
1186 {
1187 PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) );
1188 sipIsErr = 1;
1189 }
1190 else
1191 {
1192 sipRes = sipCpp->isUnsetValue( a0 );
1193 }
1194 }
1195 % End
1196#endif
1197
1203 const QgsSymbol *embeddedSymbol() const SIP_HOLDGIL;
1204
1212 void setEmbeddedSymbol( QgsSymbol *symbol SIP_TRANSFER ) SIP_HOLDGIL;
1213
1223 int fieldNameIndex( const QString &fieldName ) const SIP_HOLDGIL;
1224
1234 int approximateMemoryUsage() const;
1235
1237 operator QVariant() const
1238 {
1239 return QVariant::fromValue( *this );
1240 }
1241
1242 private:
1243
1244 QExplicitlySharedDataPointer<QgsFeaturePrivate> d;
1245
1246}; // class QgsFeature
1247
1249CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsFeature &feature ) SIP_SKIP;
1251CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsFeature &feature ) SIP_SKIP;
1252
1253// key = feature id, value = changed attributes
1254#ifndef SIP_RUN
1255typedef QMap<QgsFeatureId, QgsAttributeMap> QgsChangedAttributesMap;
1256#else
1257typedef QMap<qint64, QMap<int, QVariant> > QgsChangedAttributesMap;
1258#endif
1259
1260#include "qgsgeometry.h"
1261
1262// key = feature id, value = changed geometry
1263#ifndef SIP_RUN
1264typedef QMap<QgsFeatureId, QgsGeometry> QgsGeometryMap;
1265#else
1266typedef QMap<qint64, QgsGeometry> QgsGeometryMap;
1267#endif
1268
1269typedef QList<QgsFeature> QgsFeatureList;
1270
1271CORE_EXPORT uint qHash( const QgsFeature &key, uint seed = 0 ) SIP_SKIP;
1272
1275
1276#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:231
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:240
#define SIP_PYARGDEFAULT(value)
Definition qgis_sip.h:154
#define SIP_SKIP
Definition qgis_sip.h:134
#define SIP_TRANSFER
Definition qgis_sip.h:36
#define SIP_HOLDGIL
Definition qgis_sip.h:179
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)