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