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