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