QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 : [email protected]
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 
33 QgsFields::QgsFields( const QgsFields &other ) //NOLINT
34  : d( other.d )
35 {
36 }
37 
38 QgsFields &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 
59 bool 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 
72 bool 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 
90 bool 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 
101 void 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 
114 void 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 
128 bool QgsFields::isEmpty() const
129 {
130  return d->fields.isEmpty();
131 }
132 
133 int QgsFields::count() const
134 {
135  return d->fields.count();
136 }
137 
138 int QgsFields::size() const
139 {
140  return d->fields.count();
141 }
142 
143 QStringList 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 
153 bool 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 
163 QgsField QgsFields::at( int i ) const
164 {
165  return d->fields[i].field;
166 }
167 
168 QgsField QgsFields::field( int fieldIdx ) const
169 {
170  return d->fields[fieldIdx].field;
171 }
172 
173 QgsField 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 
197 int QgsFields::fieldOriginIndex( int fieldIdx ) const
198 {
199  return d->fields[fieldIdx].originIndex;
200 }
201 
202 int QgsFields::indexFromName( const QString &fieldName ) const
203 {
204  return d->nameToIndex.value( fieldName, -1 );
205 }
206 
207 int QgsFields::indexOf( const QString &fieldName ) const
208 {
209  return d->nameToIndex.value( fieldName, -1 );
210 }
211 
212 QList<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 
220 bool QgsFields::operator==( const QgsFields &other ) const
221 {
222  return d->fields == other.d->fields;
223 }
224 
225 QgsFields::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 
233 QgsFields::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 
241 QgsFields::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 
249 QgsFields::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 
257 QgsFields::iterator QgsFields::begin()
258 {
259  if ( d->fields.isEmpty() )
260  return iterator();
261 
262  d.detach();
263  return iterator( &d->fields.first() );
264 }
265 
266 QgsFields::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 
275 QIcon 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() );
289  }
290  }
291  return iconForFieldType( d->fields.at( fieldIdx ).field.type(), d->fields.at( fieldIdx ).field.subType() );
292 }
293 
294 QIcon QgsFields::iconForFieldType( QVariant::Type type, QVariant::Type subType )
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  default:
339  return QIcon();
340  }
341 }
342 
343 /***************************************************************************
344  * This class is considered CRITICAL and any change MUST be accompanied with
345  * full unit tests in testqgsfields.cpp.
346  * See details in QEP #17
347  ****************************************************************************/
348 
349 int QgsFields::lookupField( const QString &fieldName ) const
350 {
351  if ( fieldName.isEmpty() ) //shortcut
352  return -1;
353 
354  for ( int idx = 0; idx < count(); ++idx )
355  {
356  if ( d->fields[idx].field.name() == fieldName )
357  return idx;
358  }
359 
360  for ( int idx = 0; idx < count(); ++idx )
361  {
362  if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
363  return idx;
364  }
365 
366  for ( int idx = 0; idx < count(); ++idx )
367  {
368  const QString alias = d->fields[idx].field.alias();
369  if ( !alias.isEmpty() && QString::compare( alias, fieldName, Qt::CaseInsensitive ) == 0 )
370  return idx;
371  }
372 
373  return -1;
374 }
375 
377 {
378  const int count = d->fields.count();
379  QgsAttributeList lst;
380  lst.reserve( count );
381  for ( int i = 0; i < count; ++i )
382  lst.append( i );
383  return lst;
384 }
385 
386 /***************************************************************************
387  * This class is considered CRITICAL and any change MUST be accompanied with
388  * full unit tests in testqgsfields.cpp.
389  * See details in QEP #17
390  ****************************************************************************/
391 
392 QDataStream &operator<<( QDataStream &out, const QgsFields &fields )
393 {
394  out << static_cast< quint32 >( fields.size() );
395  for ( int i = 0; i < fields.size(); i++ )
396  {
397  out << fields.field( i );
398  }
399  return out;
400 }
401 
402 QDataStream &operator>>( QDataStream &in, QgsFields &fields )
403 {
404  fields.clear();
405  quint32 size;
406  in >> size;
407  for ( quint32 i = 0; i < size; i++ )
408  {
409  QgsField field;
410  in >> field;
411  fields.append( field );
412  }
413  return in;
414 }
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:51
QString name
Definition: qgsfield.h:60
Container of fields for a vector layer.
Definition: qgsfields.h:45
void extend(const QgsFields &other)
Extends with fields from another QgsFields container.
Definition: qgsfields.cpp:114
const_iterator constEnd() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list.
Definition: qgsfields.cpp:233
struct QgsFields::Field Field
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfields.cpp:212
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfields.cpp:376
bool operator==(const QgsFields &other) const
Definition: qgsfields.cpp:220
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.
Definition: qgsfields.cpp:202
static QIcon iconForFieldType(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns an icon corresponding to a field type.
Definition: qgsfields.cpp:294
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
void remove(int fieldIdx)
Removes the field with the given index.
Definition: qgsfields.cpp:101
@ 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.
Definition: qgsfields.cpp:133
const_iterator begin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfields.cpp:241
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:168
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)
Definition: qgsfields.cpp:184
QgsFields()
Constructor for an empty field container.
Definition: qgsfields.cpp:28
bool exists(int i) const
Returns if a field index is valid.
Definition: qgsfields.cpp:153
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
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).
Definition: qgsfields.cpp:163
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Definition: qgsfields.cpp:197
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
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.
Definition: qgsfields.cpp:275
const_iterator end() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list.
Definition: qgsfields.cpp:249
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.
Definition: qgsfields.cpp:143
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfields.cpp:225
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
QDataStream & operator>>(QDataStream &in, QgsFields &fields)
Reads fields from stream in into fields. QGIS version compatibility is not guaranteed.
Definition: qgsfields.cpp:402
QDataStream & operator<<(QDataStream &out, const QgsFields &fields)
Writes the fields to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsfields.cpp:392