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