QGIS API Documentation 3.39.0-Master (3aed037ce22)
Loading...
Searching...
No Matches
qgsfields.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfields.cpp - QgsFields
3
4 ---------------------
5 begin : 22.9.2016
6 copyright : (C) 2016 by Matthias Kuhn
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
17#include "qgsfields.h"
18#include "qgsfields_p.h"
19#include "qgsapplication.h"
20#include "qgsvariantutils.h"
21#include <QIcon>
22
23/***************************************************************************
24 * This class is considered CRITICAL and any change MUST be accompanied with
25 * full unit tests in testqgsfields.cpp.
26 * See details in QEP #17
27 ****************************************************************************/
28
30{
31 d = new QgsFieldsPrivate();
32}
33
34QgsFields::QgsFields( const QgsFields &other ) //NOLINT
35 : d( other.d )
36{
37}
38
39QgsFields &QgsFields::operator =( const QgsFields &other ) //NOLINT
40{
41 d = other.d;
42 return *this;
43}
44
45QgsFields::QgsFields( const QList<QgsField> &fields )
46{
47 d = new QgsFieldsPrivate();
48 for ( const QgsField &field : fields )
49 {
50 append( field );
51 }
52}
53
55{}
56
58{
59 d->fields.clear();
60 d->nameToIndex.clear();
61}
62
63/***************************************************************************
64 * This class is considered CRITICAL and any change MUST be accompanied with
65 * full unit tests in testqgsfields.cpp.
66 * See details in QEP #17
67 ****************************************************************************/
68
69bool QgsFields::append( const QgsField &field, Qgis::FieldOrigin origin, int originIndex )
70{
71 if ( d->nameToIndex.contains( field.name() ) )
72 return false;
73
74 if ( originIndex == -1 && origin == Qgis::FieldOrigin::Provider )
75 originIndex = d->fields.count();
76 d->fields.append( Field( field, origin, originIndex ) );
77
78 d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
79 return true;
80}
81
82bool QgsFields::append( const QList<QgsField> &fields, Qgis::FieldOrigin origin )
83{
84 for ( const QgsField &field : fields )
85 {
86 if ( d->nameToIndex.contains( field.name() ) )
87 return false;
88 }
89
90 for ( const QgsField &field : fields )
91 {
92 append( field, origin );
93 }
94 return true;
95}
96
97bool QgsFields::append( const QgsFields &fields )
98{
99 for ( const QgsField &field : fields )
100 {
101 if ( d->nameToIndex.contains( field.name() ) )
102 return false;
103 }
104
105 for ( int i = 0; i < fields.size(); ++ i )
106 {
107 append( fields.at( i ), fields.fieldOrigin( i ), fields.fieldOriginIndex( i ) );
108 }
109 return true;
110}
111
112bool QgsFields::rename( int fieldIdx, const QString &name )
113{
114 if ( !exists( fieldIdx ) )
115 return false;
116
117 if ( name.isEmpty() )
118 return false;
119
120 if ( d->nameToIndex.contains( name ) )
121 return false;
122
123 const QString oldName = d->fields[ fieldIdx ].field.name();
124 d->fields[ fieldIdx ].field.setName( name );
125 d->nameToIndex.remove( oldName );
126 d->nameToIndex.insert( name, fieldIdx );
127 return true;
128}
129
130bool QgsFields::appendExpressionField( const QgsField &field, int originIndex )
131{
132 if ( d->nameToIndex.contains( field.name() ) )
133 return false;
134
135 d->fields.append( Field( field, Qgis::FieldOrigin::Expression, originIndex ) );
136
137 d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
138 return true;
139}
140
141void QgsFields::remove( int fieldIdx )
142{
143 if ( !exists( fieldIdx ) )
144 return;
145
146 d->fields.remove( fieldIdx );
147 d->nameToIndex.clear();
148 for ( int idx = 0; idx < count(); ++idx )
149 {
150 d->nameToIndex.insert( d->fields.at( idx ).field.name(), idx );
151 }
152}
153
154void QgsFields::extend( const QgsFields &other )
155{
156 for ( int i = 0; i < other.count(); ++i )
157 {
158 append( other.at( i ), other.fieldOrigin( i ), other.fieldOriginIndex( i ) );
159 }
160}
161
162/***************************************************************************
163 * This class is considered CRITICAL and any change MUST be accompanied with
164 * full unit tests in testqgsfields.cpp.
165 * See details in QEP #17
166 ****************************************************************************/
167
169{
170 return d->fields.isEmpty();
171}
172
174{
175 return d->fields.count();
176}
177
179{
180 return d->fields.count();
181}
182
183QStringList QgsFields::names() const
184{
185 QStringList lst;
186 for ( int i = 0; i < d->fields.count(); ++i )
187 {
188 lst.append( d->fields[i].field.name() );
189 }
190 return lst;
191}
192
193bool QgsFields::exists( int i ) const
194{
195 return i >= 0 && i < d->fields.count();
196}
197
199{
200 return d->fields[i].field;
201}
202
204{
205 return d->fields[i].field;
206}
207
208QgsField QgsFields::field( int fieldIdx ) const
209{
210 return d->fields[fieldIdx].field;
211}
212
213QgsField QgsFields::field( const QString &name ) const
214{
215 return d->fields[ indexFromName( name )].field;
216}
217
218/***************************************************************************
219 * This class is considered CRITICAL and any change MUST be accompanied with
220 * full unit tests in testqgsfields.cpp.
221 * See details in QEP #17
222 ****************************************************************************/
223
225{
226 return d->fields[i].field;
227}
228
230{
231 if ( !exists( fieldIdx ) )
233
234 return d->fields[fieldIdx].origin;
235}
236
237int QgsFields::fieldOriginIndex( int fieldIdx ) const
238{
239 return d->fields[fieldIdx].originIndex;
240}
241
242int QgsFields::indexFromName( const QString &fieldName ) const
243{
244 return d->nameToIndex.value( fieldName, -1 );
245}
246
247int QgsFields::indexOf( const QString &fieldName ) const
248{
249 return d->nameToIndex.value( fieldName, -1 );
250}
251
252QList<QgsField> QgsFields::toList() const
253{
254 QList<QgsField> lst;
255 for ( int i = 0; i < d->fields.count(); ++i )
256 lst.append( d->fields[i].field );
257 return lst;
258}
259
260bool QgsFields::operator==( const QgsFields &other ) const
261{
262 return d->fields == other.d->fields;
263}
264
265QgsFields::const_iterator QgsFields::constBegin() const noexcept
266{
267 if ( d->fields.isEmpty() )
268 return const_iterator();
269
270 return const_iterator( &d->fields.first() );
271}
272
273QgsFields::const_iterator QgsFields::constEnd() const noexcept
274{
275 if ( d->fields.isEmpty() )
276 return const_iterator();
277
278 return const_iterator( &d->fields.last() + 1 );
279}
280
281QgsFields::const_iterator QgsFields::begin() const noexcept
282{
283 if ( d->fields.isEmpty() )
284 return const_iterator();
285
286 return const_iterator( &d->fields.first() );
287}
288
289QgsFields::const_iterator QgsFields::end() const noexcept
290{
291 if ( d->fields.isEmpty() )
292 return const_iterator();
293
294 return const_iterator( &d->fields.last() + 1 );
295}
296
297QgsFields::iterator QgsFields::begin()
298{
299 if ( d->fields.isEmpty() )
300 return iterator();
301
302 d.detach();
303 return iterator( &d->fields.first() );
304}
305
306QgsFields::iterator QgsFields::end()
307{
308 if ( d->fields.isEmpty() )
309 return iterator();
310
311 d.detach();
312 return iterator( &d->fields.last() + 1 );
313}
314
315QIcon QgsFields::iconForField( int fieldIdx, bool considerOrigin ) const
316{
317 if ( considerOrigin )
318 {
319 switch ( fieldOrigin( fieldIdx ) )
320 {
322 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) );
323
325 return QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/join.svg" ) );
326
327 default:
328 return iconForFieldType( d->fields.at( fieldIdx ).field.type(), d->fields.at( fieldIdx ).field.subType(), d->fields.at( fieldIdx ).field.typeName() );
329 }
330 }
331 return iconForFieldType( d->fields.at( fieldIdx ).field.type(), d->fields.at( fieldIdx ).field.subType(), d->fields.at( fieldIdx ).field.typeName() );
332}
333
334QIcon QgsFields::iconForFieldType( QMetaType::Type type, QMetaType::Type subType, const QString &typeString )
335{
336 switch ( type )
337 {
338 case QMetaType::Type::Bool:
339 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) );
340 case QMetaType::Type::Int:
341 case QMetaType::Type::UInt:
342 case QMetaType::Type::LongLong:
343 case QMetaType::Type::ULongLong:
344 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) );
345 case QMetaType::Type::Double:
346 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) );
347 case QMetaType::Type::QString:
348 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) );
349 case QMetaType::Type::QDate:
350 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) );
351 case QMetaType::Type::QDateTime:
352 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) );
353 case QMetaType::Type::QTime:
354 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) );
355 case QMetaType::Type::QByteArray:
356 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) );
357 case QMetaType::Type::QVariantList:
358 {
359 switch ( subType )
360 {
361 case QMetaType::Type::Int:
362 case QMetaType::Type::UInt:
363 case QMetaType::Type::LongLong:
364 case QMetaType::Type::ULongLong:
365 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayInteger.svg" ) );
366 case QMetaType::Type::Double:
367 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayFloat.svg" ) );
368 case QMetaType::Type::QString:
369 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayString.svg" ) );
370 default:
371 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArray.svg" ) );
372 }
373 }
374 case QMetaType::Type::QStringList:
375 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayString.svg" ) );
376 case QMetaType::Type::QVariantMap:
377 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldJson.svg" ) );
378 case QMetaType::Type::User:
379 if ( typeString.compare( QLatin1String( "geometry" ) ) == 0 )
380 {
381 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldGeometry.svg" ) );
382 }
383 else
384 {
385 return QIcon();
386 }
387
388 default:
389 return QIcon();
390 }
391}
392
393QIcon QgsFields::iconForFieldType( QVariant::Type type, QVariant::Type subType, const QString &typeString )
394{
396}
397
398/***************************************************************************
399 * This class is considered CRITICAL and any change MUST be accompanied with
400 * full unit tests in testqgsfields.cpp.
401 * See details in QEP #17
402 ****************************************************************************/
403
404int QgsFields::lookupField( const QString &fieldName ) const
405{
406 if ( fieldName.isEmpty() ) //shortcut
407 return -1;
408
409 for ( int idx = 0; idx < count(); ++idx )
410 {
411 if ( d->fields[idx].field.name() == fieldName )
412 return idx;
413 }
414
415 for ( int idx = 0; idx < count(); ++idx )
416 {
417 if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
418 return idx;
419 }
420
421 for ( int idx = 0; idx < count(); ++idx )
422 {
423 const QString alias = d->fields[idx].field.alias();
424 if ( !alias.isEmpty() && QString::compare( alias, fieldName, Qt::CaseInsensitive ) == 0 )
425 return idx;
426 }
427
428 return -1;
429}
430
432{
433 const int count = d->fields.count();
435 lst.reserve( count );
436 for ( int i = 0; i < count; ++i )
437 lst.append( i );
438 return lst;
439}
440
441/***************************************************************************
442 * This class is considered CRITICAL and any change MUST be accompanied with
443 * full unit tests in testqgsfields.cpp.
444 * See details in QEP #17
445 ****************************************************************************/
446
447QDataStream &operator<<( QDataStream &out, const QgsFields &fields )
448{
449 out << static_cast< quint32 >( fields.size() );
450 for ( int i = 0; i < fields.size(); i++ )
451 {
452 out << fields.field( i );
453 }
454 return out;
455}
456
457QDataStream &operator>>( QDataStream &in, QgsFields &fields )
458{
459 fields.clear();
460 quint32 size;
461 in >> size;
462 for ( quint32 i = 0; i < size; i++ )
463 {
464 QgsField field;
465 in >> field;
466 fields.append( field );
467 }
468 return in;
469}
FieldOrigin
Field origin.
Definition qgis.h:1454
@ Provider
Field originates from the underlying data provider of the vector layer.
@ Unknown
The field origin has not been specified.
@ Expression
Field is calculated from an expression.
@ Join
Field originates from a joined layer.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QString name
Definition qgsfield.h:62
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:69
void extend(const QgsFields &other)
Extends with fields from another QgsFields container.
int count
Definition qgsfields.h:50
const_iterator constEnd() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list.
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
bool operator==(const QgsFields &other) const
bool isEmpty
Definition qgsfields.h:49
bool appendExpressionField(const QgsField &field, int originIndex)
Appends an expression field. The field must have unique name, otherwise it is rejected (returns false...
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
void remove(int fieldIdx)
Removes the field with the given index.
const_iterator begin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
static QIcon iconForFieldType(QMetaType::Type type, QMetaType::Type subType=QMetaType::Type::UnknownType, const QString &typeString=QString())
Returns an icon corresponding to a field type.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
QgsFields & operator=(const QgsFields &other)
Definition qgsfields.cpp:39
QgsField operator[](int i) const
Gets field at particular index (must be in range 0..N-1)
QgsFields()
Constructor for an empty field container.
Definition qgsfields.cpp:29
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Q_INVOKABLE bool exists(int i) const
Returns if a field index is valid.
int size() const
Returns number of items.
void clear()
Removes all fields.
Definition qgsfields.cpp:57
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual ~QgsFields()
Definition qgsfields.cpp:54
QIcon iconForField(int fieldIdx, bool considerOrigin=false) const
Returns an icon corresponding to a field index, based on the field's type and source.
QStringList names
Definition qgsfields.h:51
const_iterator end() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list.
bool rename(int fieldIdx, const QString &name)
Renames a name of field.
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
static QMetaType::Type variantTypeToMetaType(QVariant::Type variantType)
Converts a QVariant::Type to a QMetaType::Type.
QList< int > QgsAttributeList
Definition qgsfield.h:27
QDataStream & operator>>(QDataStream &in, QgsFields &fields)
Reads fields from stream in into fields. QGIS version compatibility is not guaranteed.
QDataStream & operator<<(QDataStream &out, const QgsFields &fields)
Writes the fields to stream out. QGIS version compatibility is not guaranteed.