Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsfields.h - QgsFields 3 : : 4 : : --------------------- 5 : : begin : 22.9.2016 6 : : copyright : (C) 2016 by Matthias Kuhn 7 : : email : matthias@opengis.ch 8 : : *************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : #ifndef QGSFIELDS_H 17 : : #define QGSFIELDS_H 18 : : 19 : : 20 : : #include "qgis_sip.h" 21 : : #include "qgis_core.h" 22 : : #include "qgsfield.h" 23 : : 24 : : class QgsFieldsPrivate; 25 : : 26 : : /*************************************************************************** 27 : : * This class is considered CRITICAL and any change MUST be accompanied with 28 : : * full unit tests in testqgsfields.cpp. 29 : : * See details in QEP #17 30 : : ****************************************************************************/ 31 : : 32 : : /** 33 : : * \class QgsFields 34 : : * \ingroup core 35 : : * \brief Container of fields for a vector layer. 36 : : * 37 : : * In addition to storing a list of QgsField instances, it also: 38 : : * 39 : : * - allows quick lookups of field names to index in the list 40 : : * - keeps track of where the field definition comes from (vector data provider, joined layer or newly added from an editing operation) 41 : : * 42 : : * \note QgsFields objects are implicitly shared. 43 : : */ 44 : : class CORE_EXPORT QgsFields 45 : : { 46 : : public: 47 : : 48 : : enum FieldOrigin 49 : : { 50 : : OriginUnknown, //!< It has not been specified where the field comes from 51 : : OriginProvider, //!< Field comes from the underlying data provider of the vector layer (originIndex = index in provider's fields) 52 : : OriginJoin, //!< Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index within the join) 53 : : OriginEdit, //!< Field has been temporarily added in editing mode (originIndex = index in the list of added attributes) 54 : : OriginExpression //!< Field is calculated from an expression 55 : : }; 56 : : 57 : : #ifndef SIP_RUN 58 : : 59 : 1708 : typedef struct Field 60 : : { 61 : : Field() 62 : : {} 63 : : 64 : 422 : Field( const QgsField &f, FieldOrigin o, int oi ) 65 : 422 : : field( f ) 66 : 422 : , origin( o ) 67 : 422 : , originIndex( oi ) 68 : 422 : {} 69 : : 70 : : //! \since QGIS 2.6 71 : 0 : bool operator==( const Field &other ) const { return field == other.field && origin == other.origin && originIndex == other.originIndex; } 72 : : //! \since QGIS 2.6 73 : : bool operator!=( const Field &other ) const { return !( *this == other ); } 74 : : 75 : : QgsField field; //!< Field 76 : : FieldOrigin origin = OriginUnknown ; //!< Origin of the field 77 : : int originIndex = -1 ; //!< Index specific to the origin 78 : : } Field; 79 : : 80 : : #endif 81 : : 82 : : /** 83 : : * Constructor for an empty field container 84 : : */ 85 : : QgsFields(); 86 : : 87 : : /** 88 : : * Copy constructor 89 : : */ 90 : : QgsFields( const QgsFields &other ); 91 : : 92 : : /** 93 : : * Assignment operator 94 : : */ 95 : : QgsFields &operator =( const QgsFields &other ) SIP_SKIP; 96 : : 97 : : virtual ~QgsFields(); 98 : : 99 : : //! Removes all fields 100 : : void clear(); 101 : : 102 : : //! Appends a field. The field must have unique name, otherwise it is rejected (returns FALSE) 103 : : bool append( const QgsField &field, FieldOrigin origin = OriginProvider, int originIndex = -1 ); 104 : : 105 : : /** 106 : : * Renames a name of field. The field must have unique name, otherwise change is rejected (returns FALSE) 107 : : * \since QGIS 3.6 108 : : */ 109 : : bool rename( int fieldIdx, const QString &name ); 110 : : 111 : : //! Appends an expression field. The field must have unique name, otherwise it is rejected (returns FALSE) 112 : : bool appendExpressionField( const QgsField &field, int originIndex ); 113 : : 114 : : //! Removes a field with the given index 115 : : void remove( int fieldIdx ); 116 : : #ifdef SIP_RUN 117 : : % MethodCode 118 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 119 : : { 120 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 121 : : sipIsErr = 1; 122 : : } 123 : : else 124 : : { 125 : : sipCpp->remove( a0 ); 126 : : } 127 : : % End 128 : : #endif 129 : : 130 : : //! Extends with fields from another QgsFields container 131 : : void extend( const QgsFields &other ); 132 : : 133 : : //! Checks whether the container is empty 134 : : bool isEmpty() const; 135 : : 136 : : //! Returns number of items 137 : : int count() const; 138 : : 139 : : #ifdef SIP_RUN 140 : : int __len__() const; 141 : : % MethodCode 142 : : sipRes = sipCpp->count(); 143 : : % End 144 : : 145 : : //! Ensures that bool(obj) returns TRUE (otherwise __len__() would be used) 146 : : int __bool__() const; 147 : : % MethodCode 148 : : sipRes = true; 149 : : % End 150 : : #endif 151 : : 152 : : //! Returns number of items 153 : : int size() const; 154 : : 155 : : /** 156 : : * Returns a list with field names 157 : : * \since QGIS 3.0 158 : : */ 159 : : QStringList names() const; 160 : : 161 : : /** 162 : : * Returns if a field index is valid 163 : : * \param i Index of the field which needs to be checked 164 : : * \returns TRUE if the field exists 165 : : */ 166 : : bool exists( int i ) const; 167 : : 168 : : #ifndef SIP_RUN 169 : : //! Gets field at particular index (must be in range 0..N-1) 170 : : QgsField operator[]( int i ) const; 171 : : #endif 172 : : 173 : : //! Gets field at particular index (must be in range 0..N-1) 174 : : QgsField &operator[]( int i ) SIP_FACTORY; 175 : : #ifdef SIP_RUN 176 : : % MethodCode 177 : : SIP_SSIZE_T idx = sipConvertFromSequenceIndex( a0, sipCpp->count() ); 178 : : if ( idx < 0 ) 179 : : sipIsErr = 1; 180 : : else 181 : : sipRes = new QgsField( sipCpp->operator[]( idx ) ); 182 : : % End 183 : : #endif 184 : : 185 : : //! Gets field at particular index (must be in range 0..N-1) 186 : : QgsField at( int i ) const SIP_FACTORY; 187 : : #ifdef SIP_RUN 188 : : % MethodCode 189 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 190 : : { 191 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 192 : : sipIsErr = 1; 193 : : } 194 : : else 195 : : { 196 : : sipRes = new QgsField( sipCpp->at( a0 ) ); 197 : : } 198 : : % End 199 : : #endif 200 : : 201 : : //! Gets field at particular index (must be in range 0..N-1) 202 : : QgsField field( int fieldIdx ) const SIP_FACTORY; 203 : : #ifdef SIP_RUN 204 : : % MethodCode 205 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 206 : : { 207 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 208 : : sipIsErr = 1; 209 : : } 210 : : else 211 : : { 212 : : sipRes = new QgsField( sipCpp->field( a0 ) ); 213 : : } 214 : : % End 215 : : #endif 216 : : 217 : : //! Gets field with matching name 218 : : QgsField field( const QString &name ) const SIP_FACTORY; 219 : : #ifdef SIP_RUN 220 : : % MethodCode 221 : : int fieldIdx = sipCpp->indexFromName( *a0 ); 222 : : if ( fieldIdx == -1 ) 223 : : { 224 : : PyErr_SetString( PyExc_KeyError, a0->toLatin1() ); 225 : : sipIsErr = 1; 226 : : } 227 : : else 228 : : { 229 : : sipRes = new QgsField( sipCpp->field( *a0 ) ); 230 : : } 231 : : % End 232 : : #endif 233 : : 234 : : //! Gets field's origin (value from an enumeration) 235 : : FieldOrigin fieldOrigin( int fieldIdx ) const; 236 : : #ifdef SIP_RUN 237 : : % MethodCode 238 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 239 : : { 240 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 241 : : sipIsErr = 1; 242 : : } 243 : : else 244 : : { 245 : : sipRes = sipCpp->fieldOrigin( a0 ); 246 : : } 247 : : % End 248 : : #endif 249 : : 250 : : //! Gets field's origin index (its meaning is specific to each type of origin) 251 : : int fieldOriginIndex( int fieldIdx ) const; 252 : : #ifdef SIP_RUN 253 : : % MethodCode 254 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 255 : : { 256 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 257 : : sipIsErr = 1; 258 : : } 259 : : else 260 : : { 261 : : sipRes = sipCpp->fieldOriginIndex( a0 ); 262 : : } 263 : : % End 264 : : #endif 265 : : 266 : : /** 267 : : * Gets the field index from the field name. 268 : : * This method is case sensitive and only matches the data source 269 : : * name of the field. 270 : : * Alias for indexOf 271 : : * 272 : : * \param fieldName The name of the field. 273 : : * 274 : : * \returns The field index if found or -1 in case it cannot be found. 275 : : * \see lookupField For a more tolerant alternative. 276 : : */ 277 : : int indexFromName( const QString &fieldName ) const; 278 : : 279 : : /** 280 : : * Gets the field index from the field name. 281 : : * This method is case sensitive and only matches the data source 282 : : * name of the field. 283 : : * 284 : : * \param fieldName The name of the field. 285 : : * 286 : : * \returns The field index if found or -1 in case it cannot be found. 287 : : * \see lookupField For a more tolerant alternative. 288 : : * \since QGIS 3.0 289 : : */ 290 : : int indexOf( const QString &fieldName ) const; 291 : : 292 : : /** 293 : : * Looks up field's index from the field name. 294 : : * This method matches in the following order: 295 : : * 296 : : * 1. The exact field name taking case sensitivity into account 297 : : * 2. Looks for the field name by case insensitive comparison 298 : : * 3. The field alias (case insensitive) 299 : : * 300 : : * \param fieldName The name to look for. 301 : : * 302 : : * \returns The field index if found or -1 in case it cannot be found. 303 : : * \see indexFromName For a more performant and precise but less tolerant alternative. 304 : : * \since QGIS 2.4 305 : : */ 306 : : int lookupField( const QString &fieldName ) const; 307 : : 308 : : /** 309 : : * Utility function to get list of attribute indexes 310 : : * \since QGIS 2.4 311 : : */ 312 : : QgsAttributeList allAttributesList() const; 313 : : 314 : : //! Utility function to return a list of QgsField instances 315 : : QList<QgsField> toList() const; 316 : : 317 : : //! \since QGIS 2.6 318 : : bool operator==( const QgsFields &other ) const; 319 : : //! \since QGIS 2.6 320 : 79 : bool operator!=( const QgsFields &other ) const { return !( *this == other ); } 321 : : 322 : : /** 323 : : * Returns an icon corresponding to a field index, based on the field's type and source 324 : : * \param fieldIdx the field index 325 : : * \param considerOrigin if TRUE the icon will the origin of the field 326 : : * \since QGIS 2.14 327 : : */ 328 : : QIcon iconForField( int fieldIdx, bool considerOrigin = false ) const SIP_FACTORY; 329 : : #ifdef SIP_RUN 330 : : % MethodCode 331 : : if ( a0 < 0 || a0 >= sipCpp->count() ) 332 : : { 333 : : PyErr_SetString( PyExc_KeyError, QByteArray::number( a0 ) ); 334 : : sipIsErr = 1; 335 : : } 336 : : else 337 : : { 338 : : sipRes = new QIcon( sipCpp->iconForField( a0 ) ); 339 : : } 340 : : % End 341 : : #endif 342 : : 343 : : 344 : : /** 345 : : * Returns an icon corresponding to a field \a type 346 : : * \since QGIS 3.16 347 : : */ 348 : : static QIcon iconForFieldType( const QVariant::Type &type ) SIP_FACTORY; 349 : : 350 : : //! Allows direct construction of QVariants from fields. 351 : : operator QVariant() const 352 : : { 353 : : return QVariant::fromValue( *this ); 354 : : } 355 : : 356 : : #ifdef SIP_RUN 357 : : 358 : : void __setitem__( int key, const QgsField &field ); 359 : : % MethodCode 360 : : int idx = ( int )sipConvertFromSequenceIndex( a0, sipCpp->count() ); 361 : : if ( idx < 0 ) 362 : : sipIsErr = 1; 363 : : else 364 : : ( *sipCpp )[idx] = *a1; 365 : : % End 366 : : 367 : : #endif 368 : : 369 : : #ifndef SIP_RUN 370 : : 371 : : ///@cond PRIVATE 372 : : 373 : : class const_iterator; 374 : : 375 : : class iterator 376 : : { 377 : : public: 378 : 0 : QgsFields::Field *d = nullptr; 379 : : typedef std::random_access_iterator_tag iterator_category; 380 : : typedef qptrdiff difference_type; 381 : : 382 : 0 : inline iterator() 383 : 0 : {} 384 : : 385 : 0 : inline iterator( QgsFields::Field *n ) 386 : 0 : : d( n ) 387 : 0 : {} 388 : : 389 : 0 : inline QgsField &operator*() const { return d->field; } 390 : : inline QgsField *operator->() const { return &d->field; } 391 : : inline QgsField &operator[]( difference_type j ) const { return d[j].field; } 392 : : inline bool operator==( const iterator &o ) const noexcept { return d == o.d; } // clazy:exclude=function-args-by-value 393 : 0 : inline bool operator!=( const iterator &o ) const noexcept { return d != o.d; } // clazy:exclude=function-args-by-value 394 : : inline bool operator<( const iterator &other ) const noexcept { return d < other.d; } // clazy:exclude=function-args-by-value 395 : : inline bool operator<=( const iterator &other ) const noexcept { return d <= other.d; } // clazy:exclude=function-args-by-value 396 : : inline bool operator>( const iterator &other ) const noexcept { return d > other.d; } // clazy:exclude=function-args-by-value 397 : : inline bool operator>=( const iterator &other ) const noexcept { return d >= other.d; } // clazy:exclude=function-args-by-value 398 : : 399 : 0 : inline iterator &operator++() { ++d; return *this; } 400 : : inline iterator operator++( int ) { QgsFields::Field *n = d; ++d; return n; } 401 : : inline iterator &operator--() { d--; return *this; } 402 : : inline iterator operator--( int ) { QgsFields::Field *n = d; d--; return n; } 403 : : inline iterator &operator+=( difference_type j ) { d += j; return *this; } 404 : : inline iterator &operator-=( difference_type j ) { d -= j; return *this; } 405 : : inline iterator operator+( difference_type j ) const { return iterator( d + j ); } 406 : : inline iterator operator-( difference_type j ) const { return iterator( d - j ); } 407 : : inline int operator-( iterator j ) const { return int( d - j.d ); } 408 : : }; 409 : : friend class iterator; 410 : : 411 : : class const_iterator // clazy:exclude=rule-of-three 412 : : { 413 : : public: 414 : 84 : const QgsFields::Field *d = nullptr; 415 : : 416 : : typedef std::random_access_iterator_tag iterator_category; 417 : : typedef qptrdiff difference_type; 418 : : 419 : 84 : inline const_iterator() 420 : 84 : {} 421 : : 422 : 384 : inline const_iterator( const QgsFields::Field *f ) 423 : 384 : : d( f ) {} 424 : : inline const_iterator( const const_iterator &o ) 425 : : : d( o.d ) {} 426 : : inline explicit const_iterator( const iterator &o ) // clazy:exclude=function-args-by-value 427 : : : d( o.d ) {} 428 : 252 : inline const QgsField &operator*() const { return d->field; } 429 : : inline const QgsField *operator->() const { return &d->field; } 430 : : inline const QgsField &operator[]( difference_type j ) const noexcept { return d[j].field; } 431 : : inline bool operator==( const const_iterator &o ) const noexcept { return d == o.d; } 432 : 486 : inline bool operator!=( const const_iterator &o ) const noexcept { return d != o.d; } 433 : : inline bool operator<( const const_iterator &other ) const noexcept { return d < other.d; } 434 : : inline bool operator<=( const const_iterator &other ) const noexcept { return d <= other.d; } 435 : : inline bool operator>( const const_iterator &other ) const noexcept { return d > other.d; } 436 : : inline bool operator>=( const const_iterator &other ) const noexcept { return d >= other.d; } 437 : 252 : inline const_iterator &operator++() { ++d; return *this; } 438 : : inline const_iterator operator++( int ) { const QgsFields::Field *n = d; ++d; return n; } 439 : : inline const_iterator &operator--() { d--; return *this; } 440 : : inline const_iterator operator--( int ) { const QgsFields::Field *n = d; --d; return n; } 441 : : inline const_iterator &operator+=( difference_type j ) { d += j; return *this; } 442 : : inline const_iterator &operator-=( difference_type j ) { d -= j; return *this; } 443 : : inline const_iterator operator+( difference_type j ) const { return const_iterator( d + j ); } 444 : : inline const_iterator operator-( difference_type j ) const { return const_iterator( d - j ); } 445 : : inline int operator-( const_iterator j ) const { return int( d - j.d ); } // clazy:exclude=function-args-by-ref 446 : : private: 447 : : const_iterator &operator= ( const const_iterator & ) = delete; 448 : : }; 449 : : friend class const_iterator; 450 : : ///@endcond 451 : : 452 : : 453 : : /** 454 : : * Returns a const STL-style iterator pointing to the first item in the list. 455 : : * 456 : : * \note not available in Python bindings 457 : : * \since QGIS 2.16 458 : : */ 459 : : const_iterator constBegin() const noexcept; 460 : : 461 : : /** 462 : : * Returns a const STL-style iterator pointing to the imaginary item after the last item in the list. 463 : : * 464 : : * \note not available in Python bindings 465 : : * \since QGIS 2.16 466 : : */ 467 : : const_iterator constEnd() const noexcept; 468 : : 469 : : /** 470 : : * Returns a const STL-style iterator pointing to the first item in the list. 471 : : * 472 : : * \note not available in Python bindings 473 : : * \since QGIS 2.16 474 : : */ 475 : : const_iterator begin() const noexcept; 476 : : 477 : : /** 478 : : * Returns a const STL-style iterator pointing to the imaginary item after the last item in the list. 479 : : * 480 : : * \note not available in Python bindings 481 : : * \since QGIS 2.16 482 : : */ 483 : : const_iterator end() const noexcept; 484 : : 485 : : /** 486 : : * Returns an STL-style iterator pointing to the first item in the list. 487 : : * 488 : : * \note not available in Python bindings 489 : : * \since QGIS 2.16 490 : : */ 491 : : iterator begin(); 492 : : 493 : : 494 : : /** 495 : : * Returns an STL-style iterator pointing to the imaginary item after the last item in the list. 496 : : * 497 : : * \note not available in Python bindings 498 : : * \since QGIS 2.16 499 : : */ 500 : : iterator end(); 501 : : 502 : : #endif 503 : : 504 : : private: 505 : : 506 : : QSharedDataPointer<QgsFieldsPrivate> d; 507 : : 508 : : }; 509 : : 510 : 200 : Q_DECLARE_METATYPE( QgsFields ) 511 : : 512 : : //! Writes the fields to stream out. QGIS version compatibility is not guaranteed. 513 : : CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsFields &fields ); 514 : : //! Reads fields from stream in into fields. QGIS version compatibility is not guaranteed. 515 : : CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsFields &fields ); 516 : : 517 : : #endif // QGSFIELDS_H