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