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