QGIS API Documentation 3.36.0-Maidenhead (09951dc0acf)
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 <QIcon>
21
22/***************************************************************************
23 * This class is considered CRITICAL and any change MUST be accompanied with
24 * full unit tests in testqgsfields.cpp.
25 * See details in QEP #17
26 ****************************************************************************/
27
29{
30 d = new QgsFieldsPrivate();
31}
32
33QgsFields::QgsFields( const QgsFields &other ) //NOLINT
34 : d( other.d )
35{
36}
37
38QgsFields &QgsFields::operator =( const QgsFields &other ) //NOLINT
39{
40 d = other.d;
41 return *this;
42}
43
45{}
46
48{
49 d->fields.clear();
50 d->nameToIndex.clear();
51}
52
53/***************************************************************************
54 * This class is considered CRITICAL and any change MUST be accompanied with
55 * full unit tests in testqgsfields.cpp.
56 * See details in QEP #17
57 ****************************************************************************/
58
59bool QgsFields::append( const QgsField &field, FieldOrigin origin, int originIndex )
60{
61 if ( d->nameToIndex.contains( field.name() ) )
62 return false;
63
64 if ( originIndex == -1 && origin == OriginProvider )
65 originIndex = d->fields.count();
66 d->fields.append( Field( field, origin, originIndex ) );
67
68 d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
69 return true;
70}
71
72bool QgsFields::rename( int fieldIdx, const QString &name )
73{
74 if ( !exists( fieldIdx ) )
75 return false;
76
77 if ( name.isEmpty() )
78 return false;
79
80 if ( d->nameToIndex.contains( name ) )
81 return false;
82
83 const QString oldName = d->fields[ fieldIdx ].field.name();
84 d->fields[ fieldIdx ].field.setName( name );
85 d->nameToIndex.remove( oldName );
86 d->nameToIndex.insert( name, fieldIdx );
87 return true;
88}
89
90bool QgsFields::appendExpressionField( const QgsField &field, int originIndex )
91{
92 if ( d->nameToIndex.contains( field.name() ) )
93 return false;
94
95 d->fields.append( Field( field, OriginExpression, originIndex ) );
96
97 d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
98 return true;
99}
100
101void QgsFields::remove( int fieldIdx )
102{
103 if ( !exists( fieldIdx ) )
104 return;
105
106 d->fields.remove( fieldIdx );
107 d->nameToIndex.clear();
108 for ( int idx = 0; idx < count(); ++idx )
109 {
110 d->nameToIndex.insert( d->fields.at( idx ).field.name(), idx );
111 }
112}
113
114void QgsFields::extend( const QgsFields &other )
115{
116 for ( int i = 0; i < other.count(); ++i )
117 {
118 append( other.at( i ), other.fieldOrigin( i ), other.fieldOriginIndex( i ) );
119 }
120}
121
122/***************************************************************************
123 * This class is considered CRITICAL and any change MUST be accompanied with
124 * full unit tests in testqgsfields.cpp.
125 * See details in QEP #17
126 ****************************************************************************/
127
129{
130 return d->fields.isEmpty();
131}
132
134{
135 return d->fields.count();
136}
137
139{
140 return d->fields.count();
141}
142
143QStringList QgsFields::names() const
144{
145 QStringList lst;
146 for ( int i = 0; i < d->fields.count(); ++i )
147 {
148 lst.append( d->fields[i].field.name() );
149 }
150 return lst;
151}
152
153bool QgsFields::exists( int i ) const
154{
155 return i >= 0 && i < d->fields.count();
156}
157
159{
160 return d->fields[i].field;
161}
162
164{
165 return d->fields[i].field;
166}
167
168QgsField QgsFields::field( int fieldIdx ) const
169{
170 return d->fields[fieldIdx].field;
171}
172
173QgsField QgsFields::field( const QString &name ) const
174{
175 return d->fields[ indexFromName( name )].field;
176}
177
178/***************************************************************************
179 * This class is considered CRITICAL and any change MUST be accompanied with
180 * full unit tests in testqgsfields.cpp.
181 * See details in QEP #17
182 ****************************************************************************/
183
185{
186 return d->fields[i].field;
187}
188
190{
191 if ( !exists( fieldIdx ) )
192 return OriginUnknown;
193
194 return d->fields[fieldIdx].origin;
195}
196
197int QgsFields::fieldOriginIndex( int fieldIdx ) const
198{
199 return d->fields[fieldIdx].originIndex;
200}
201
202int QgsFields::indexFromName( const QString &fieldName ) const
203{
204 return d->nameToIndex.value( fieldName, -1 );
205}
206
207int QgsFields::indexOf( const QString &fieldName ) const
208{
209 return d->nameToIndex.value( fieldName, -1 );
210}
211
212QList<QgsField> QgsFields::toList() const
213{
214 QList<QgsField> lst;
215 for ( int i = 0; i < d->fields.count(); ++i )
216 lst.append( d->fields[i].field );
217 return lst;
218}
219
220bool QgsFields::operator==( const QgsFields &other ) const
221{
222 return d->fields == other.d->fields;
223}
224
225QgsFields::const_iterator QgsFields::constBegin() const noexcept
226{
227 if ( d->fields.isEmpty() )
228 return const_iterator();
229
230 return const_iterator( &d->fields.first() );
231}
232
233QgsFields::const_iterator QgsFields::constEnd() const noexcept
234{
235 if ( d->fields.isEmpty() )
236 return const_iterator();
237
238 return const_iterator( &d->fields.last() + 1 );
239}
240
241QgsFields::const_iterator QgsFields::begin() const noexcept
242{
243 if ( d->fields.isEmpty() )
244 return const_iterator();
245
246 return const_iterator( &d->fields.first() );
247}
248
249QgsFields::const_iterator QgsFields::end() const noexcept
250{
251 if ( d->fields.isEmpty() )
252 return const_iterator();
253
254 return const_iterator( &d->fields.last() + 1 );
255}
256
257QgsFields::iterator QgsFields::begin()
258{
259 if ( d->fields.isEmpty() )
260 return iterator();
261
262 d.detach();
263 return iterator( &d->fields.first() );
264}
265
266QgsFields::iterator QgsFields::end()
267{
268 if ( d->fields.isEmpty() )
269 return iterator();
270
271 d.detach();
272 return iterator( &d->fields.last() + 1 );
273}
274
275QIcon QgsFields::iconForField( int fieldIdx, bool considerOrigin ) const
276{
277 if ( considerOrigin )
278 {
279 switch ( fieldOrigin( fieldIdx ) )
280 {
282 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpression.svg" ) );
283
285 return QgsApplication::getThemeIcon( QStringLiteral( "/propertyicons/join.svg" ) );
286
287 default:
288 return iconForFieldType( d->fields.at( fieldIdx ).field.type(), d->fields.at( fieldIdx ).field.subType(), d->fields.at( fieldIdx ).field.typeName() );
289 }
290 }
291 return iconForFieldType( d->fields.at( fieldIdx ).field.type(), d->fields.at( fieldIdx ).field.subType(), d->fields.at( fieldIdx ).field.typeName() );
292}
293
294QIcon QgsFields::iconForFieldType( QVariant::Type type, QVariant::Type subType, const QString &typeString )
295{
296 switch ( type )
297 {
298 case QVariant::Bool:
299 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBool.svg" ) );
300 case QVariant::Int:
301 case QVariant::UInt:
302 case QVariant::LongLong:
303 case QVariant::ULongLong:
304 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldInteger.svg" ) );
305 case QVariant::Double:
306 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldFloat.svg" ) );
307 case QVariant::String:
308 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldText.svg" ) );
309 case QVariant::Date:
310 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDate.svg" ) );
311 case QVariant::DateTime:
312 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldDateTime.svg" ) );
313 case QVariant::Time:
314 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldTime.svg" ) );
315 case QVariant::ByteArray:
316 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldBinary.svg" ) );
317 case QVariant::List:
318 {
319 switch ( subType )
320 {
321 case QVariant::Int:
322 case QVariant::UInt:
323 case QVariant::LongLong:
324 case QVariant::ULongLong:
325 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayInteger.svg" ) );
326 case QVariant::Double:
327 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayFloat.svg" ) );
328 case QVariant::String:
329 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayString.svg" ) );
330 default:
331 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArray.svg" ) );
332 }
333 }
334 case QVariant::StringList:
335 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldArrayString.svg" ) );
336 case QVariant::Map:
337 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldJson.svg" ) );
338 case QVariant::UserType:
339 if ( typeString.compare( QLatin1String( "geometry" ) ) == 0 )
340 {
341 return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFieldGeometry.svg" ) );
342 }
343 else
344 {
345 return QIcon();
346 }
347
348 default:
349 return QIcon();
350 }
351}
352
353/***************************************************************************
354 * This class is considered CRITICAL and any change MUST be accompanied with
355 * full unit tests in testqgsfields.cpp.
356 * See details in QEP #17
357 ****************************************************************************/
358
359int QgsFields::lookupField( const QString &fieldName ) const
360{
361 if ( fieldName.isEmpty() ) //shortcut
362 return -1;
363
364 for ( int idx = 0; idx < count(); ++idx )
365 {
366 if ( d->fields[idx].field.name() == fieldName )
367 return idx;
368 }
369
370 for ( int idx = 0; idx < count(); ++idx )
371 {
372 if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
373 return idx;
374 }
375
376 for ( int idx = 0; idx < count(); ++idx )
377 {
378 const QString alias = d->fields[idx].field.alias();
379 if ( !alias.isEmpty() && QString::compare( alias, fieldName, Qt::CaseInsensitive ) == 0 )
380 return idx;
381 }
382
383 return -1;
384}
385
387{
388 const int count = d->fields.count();
390 lst.reserve( count );
391 for ( int i = 0; i < count; ++i )
392 lst.append( i );
393 return lst;
394}
395
396/***************************************************************************
397 * This class is considered CRITICAL and any change MUST be accompanied with
398 * full unit tests in testqgsfields.cpp.
399 * See details in QEP #17
400 ****************************************************************************/
401
402QDataStream &operator<<( QDataStream &out, const QgsFields &fields )
403{
404 out << static_cast< quint32 >( fields.size() );
405 for ( int i = 0; i < fields.size(); i++ )
406 {
407 out << fields.field( i );
408 }
409 return out;
410}
411
412QDataStream &operator>>( QDataStream &in, QgsFields &fields )
413{
414 fields.clear();
415 quint32 size;
416 in >> size;
417 for ( quint32 i = 0; i < size; i++ )
418 {
419 QgsField field;
420 in >> field;
421 fields.append( field );
422 }
423 return in;
424}
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:45
void extend(const QgsFields &other)
Extends with fields from another QgsFields container.
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 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:90
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition qgsfields.cpp:59
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
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.
@ OriginExpression
Field is calculated from an expression.
Definition qgsfields.h:54
@ OriginUnknown
It has not been specified where the field comes from.
Definition qgsfields.h:50
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition qgsfields.h:51
int count() const
Returns number of items.
static QIcon iconForFieldType(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid, const QString &typeString=QString())
Returns an icon corresponding to a field type.
const_iterator begin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
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:38
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:28
bool exists(int i) const
Returns if a field index is valid.
bool isEmpty() const
Checks whether the container is empty.
int size() const
Returns number of items.
void clear()
Removes all fields.
Definition qgsfields.cpp:47
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).
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
virtual ~QgsFields()
Definition qgsfields.cpp:44
QIcon iconForField(int fieldIdx, bool considerOrigin=false) const
Returns an icon corresponding to a field index, based on the field's type and source.
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:72
QStringList names() const
Returns a list with field names.
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
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.