QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsfield.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfield.cpp - Describes a field in a layer or table
3  --------------------------------------
4  Date : 01-Jan-2004
5  Copyright : (C) 2004 by Gary E.Sherman
6  email : sherman at mrcc.com
7 
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 "qgsfield.h"
18 #include "qgsfield_p.h"
19 #include "qgis.h"
20 #include "qgsapplication.h"
21 
22 #include <QSettings>
23 #include <QDataStream>
24 #include <QtCore/qmath.h>
25 #include <QIcon>
26 
27 /***************************************************************************
28  * This class is considered CRITICAL and any change MUST be accompanied with
29  * full unit tests in testqgsfield.cpp.
30  * See details in QEP #17
31  ****************************************************************************/
32 
33 #if 0
34 QgsField::QgsField( QString nam, QString typ, int len, int prec, bool num,
35  QString comment )
36  : mName( nam ), mType( typ ), mLength( len ), mPrecision( prec ), mNumeric( num )
37  , mComment( comment )
38 {
39  // This function used to lower case the field name since some stores
40  // use upper case (eg. shapefiles), but that caused problems with
41  // attribute actions getting confused between uppercase and
42  // lowercase versions of the attribute names, so just leave the
43  // names how they are now.
44 }
45 #endif
46 QgsField::QgsField( const QString& name, QVariant::Type type,
47  const QString& typeName, int len, int prec, const QString& comment )
48 {
49  d = new QgsFieldPrivate( name, type, typeName, len, prec, comment );
50 }
51 
53  : d( other.d )
54 {
55 
56 }
57 
58 /***************************************************************************
59  * This class is considered CRITICAL and any change MUST be accompanied with
60  * full unit tests in testqgsfield.cpp.
61  * See details in QEP #17
62  ****************************************************************************/
63 
65 {
66  d = other.d;
67  return *this;
68 }
69 
71 {
72 }
73 
74 bool QgsField::operator==( const QgsField& other ) const
75 {
76  return *( other.d ) == *d;
77 }
78 
79 bool QgsField::operator!=( const QgsField& other ) const
80 {
81  return !( *this == other );
82 }
83 
84 QString QgsField::name() const
85 {
86  return d->name;
87 }
88 
90 {
91  if ( !d->alias.isEmpty() )
92  return d->alias;
93  else
94  return d->name;
95 }
96 
97 QVariant::Type QgsField::type() const
98 {
99  return d->type;
100 }
101 
103 {
104  return d->typeName;
105 }
106 
107 int QgsField::length() const
108 {
109  return d->length;
110 }
111 
112 int QgsField::precision() const
113 {
114  return d->precision;
115 }
116 
118 {
119  return d->comment;
120 }
121 
122 bool QgsField::isNumeric() const
123 {
124  return d->type == QVariant::Double || d->type == QVariant::Int || d->type == QVariant::UInt || d->type == QVariant::LongLong || d->type == QVariant::ULongLong;
125 }
126 
127 /***************************************************************************
128  * This class is considered CRITICAL and any change MUST be accompanied with
129  * full unit tests in testqgsfield.cpp.
130  * See details in QEP #17
131  ****************************************************************************/
132 
134 {
135  d->name = name;
136 }
137 
138 void QgsField::setType( QVariant::Type type )
139 {
140  d->type = type;
141 }
142 
144 {
145  d->typeName = typeName;
146 }
147 
148 void QgsField::setLength( int len )
149 {
150  d->length = len;
151 }
153 {
154  d->precision = precision;
155 }
156 
158 {
159  d->comment = comment;
160 }
161 
163 {
164  return d->defaultValueExpression;
165 }
166 
168 {
169  d->defaultValueExpression = expression;
170 }
171 
172 QString QgsField::alias() const
173 {
174  return d->alias;
175 }
176 
178 {
179  d->alias = alias;
180 }
181 
182 /***************************************************************************
183  * This class is considered CRITICAL and any change MUST be accompanied with
184  * full unit tests in testqgsfield.cpp.
185  * See details in QEP #17
186  ****************************************************************************/
187 
189 {
190  if ( v.isNull() )
191  {
192  QSettings settings;
193  return settings.value( "qgis/nullValue", "NULL" ).toString();
194  }
195 
196  if ( d->type == QVariant::Double && d->precision > 0 )
197  return QString::number( v.toDouble(), 'f', d->precision );
198 
199  return v.toString();
200 }
201 
202 /***************************************************************************
203  * This class is considered CRITICAL and any change MUST be accompanied with
204  * full unit tests in testqgsfield.cpp.
205  * See details in QEP #17
206  ****************************************************************************/
207 
209 {
210  if ( v.isNull() )
211  {
212  v.convert( d->type );
213  return true;
214  }
215 
216  if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
217  {
218  v = QVariant( d->type );
219  return false;
220  }
221 
222  //String representations of doubles in QVariant will return false to convert( QVariant::Int )
223  //work around this by first converting to double, and then checking whether the double is convertible to int
224  if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
225  {
226  bool ok = false;
227  double dbl = v.toDouble( &ok );
228  if ( !ok )
229  {
230  //couldn't convert to number
231  v = QVariant( d->type );
232  return false;
233  }
234 
235  double round = qgsRound( dbl );
236  if ( round > INT_MAX || round < -INT_MAX )
237  {
238  //double too large to fit in int
239  v = QVariant( d->type );
240  return false;
241  }
242  v = QVariant( qRound( dbl ) );
243  return true;
244  }
245 
246  if ( !v.convert( d->type ) )
247  {
248  v = QVariant( d->type );
249  return false;
250  }
251 
252  if ( d->type == QVariant::Double && d->precision > 0 )
253  {
254  double s = qPow( 10, d->precision );
255  double d = v.toDouble() * s;
256  v = QVariant(( d < 0 ? ceil( d - 0.5 ) : floor( d + 0.5 ) ) / s );
257  return true;
258  }
259 
260  if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
261  {
262  v = v.toString().left( d->length );
263  return false;
264  }
265 
266  return true;
267 }
268 
269 /***************************************************************************
270  * This class is considered CRITICAL and any change MUST be accompanied with
271  * full unit tests in testqgsfield.cpp.
272  * See details in QEP #17
273  ****************************************************************************/
274 
276 {
277  out << field.name();
278  out << static_cast< quint32 >( field.type() );
279  out << field.typeName();
280  out << field.length();
281  out << field.precision();
282  out << field.comment();
283  out << field.alias();
284  out << field.defaultValueExpression();
285  return out;
286 }
287 
289 {
290  quint32 type, length, precision;
292  in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression;
293  field.setName( name );
294  field.setType( static_cast< QVariant::Type >( type ) );
295  field.setTypeName( typeName );
296  field.setLength( static_cast< int >( length ) );
297  field.setPrecision( static_cast< int >( precision ) );
298  field.setComment( comment );
299  field.setAlias( alias );
300  field.setDefaultValueExpression( defaultValueExpression );
301  return in;
302 }
303 
305 
306 
307 /***************************************************************************
308  * This class is considered CRITICAL and any change MUST be accompanied with
309  * full unit tests in testqgsfields.cpp.
310  * See details in QEP #17
311  ****************************************************************************/
312 
314 {
315  d = new QgsFieldsPrivate();
316 }
317 
319  : d( other.d )
320 {
321 }
322 
324 {
325  d = other.d;
326  return *this;
327 }
328 
330 {
331 
332 }
333 
335 {
336  d->fields.clear();
337  d->nameToIndex.clear();
338 }
339 
340 /***************************************************************************
341  * This class is considered CRITICAL and any change MUST be accompanied with
342  * full unit tests in testqgsfields.cpp.
343  * See details in QEP #17
344  ****************************************************************************/
345 
346 bool QgsFields::append( const QgsField& field, FieldOrigin origin, int originIndex )
347 {
348  if ( d->nameToIndex.contains( field.name() ) )
349  return false;
350 
351  if ( originIndex == -1 && origin == OriginProvider )
352  originIndex = d->fields.count();
353  d->fields.append( Field( field, origin, originIndex ) );
354 
355  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
356  return true;
357 }
358 
359 bool QgsFields::appendExpressionField( const QgsField& field, int originIndex )
360 {
361  if ( d->nameToIndex.contains( field.name() ) )
362  return false;
363 
364  d->fields.append( Field( field, OriginExpression, originIndex ) );
365 
366  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
367  return true;
368 }
369 
370 void QgsFields::remove( int fieldIdx )
371 {
372  if ( !exists( fieldIdx ) )
373  return;
374 
375  d->fields.remove( fieldIdx );
376  d->nameToIndex.clear();
377  for ( int idx = 0; idx < count(); ++idx )
378  {
379  d->nameToIndex.insert( d->fields.at( idx ).field.name(), idx );
380  }
381 }
382 
383 void QgsFields::extend( const QgsFields& other )
384 {
385  for ( int i = 0; i < other.count(); ++i )
386  {
387  append( other.at( i ), other.fieldOrigin( i ), other.fieldOriginIndex( i ) );
388  }
389 }
390 
391 /***************************************************************************
392  * This class is considered CRITICAL and any change MUST be accompanied with
393  * full unit tests in testqgsfields.cpp.
394  * See details in QEP #17
395  ****************************************************************************/
396 
397 bool QgsFields::isEmpty() const
398 {
399  return d->fields.isEmpty();
400 }
401 
402 int QgsFields::count() const
403 {
404  return d->fields.count();
405 }
406 
407 int QgsFields::size() const
408 {
409  return d->fields.count();
410 }
411 
412 bool QgsFields::exists( int i ) const
413 {
414  return i >= 0 && i < d->fields.count();
415 }
416 
418 {
419  return d->fields[i].field;
420 }
421 
422 const QgsField &QgsFields::at( int i ) const
423 {
424  return d->fields[i].field;
425 }
426 
427 const QgsField &QgsFields::field( int fieldIdx ) const
428 {
429  return d->fields[fieldIdx].field;
430 }
431 
432 const QgsField &QgsFields::field( const QString &name ) const
433 {
434  return d->fields[ indexFromName( name )].field;
435 }
436 
437 /***************************************************************************
438  * This class is considered CRITICAL and any change MUST be accompanied with
439  * full unit tests in testqgsfields.cpp.
440  * See details in QEP #17
441  ****************************************************************************/
442 
443 const QgsField &QgsFields::operator[]( int i ) const
444 {
445  return d->fields[i].field;
446 }
447 
449 {
450  if ( !exists( fieldIdx ) )
451  return OriginUnknown;
452 
453  return d->fields[fieldIdx].origin;
454 }
455 
456 int QgsFields::fieldOriginIndex( int fieldIdx ) const
457 {
458  return d->fields[fieldIdx].originIndex;
459 }
460 
461 int QgsFields::indexFromName( const QString &name ) const
462 {
463  return d->nameToIndex.value( name, -1 );
464 }
465 
467 {
468  QList<QgsField> lst;
469  for ( int i = 0; i < d->fields.count(); ++i )
470  lst.append( d->fields[i].field );
471  return lst;
472 }
473 
474 bool QgsFields::operator==( const QgsFields &other ) const
475 {
476  return d->fields == other.d->fields;
477 }
478 
479 QgsFields::const_iterator QgsFields::constBegin() const noexcept
480 {
481  if ( d->fields.isEmpty() )
482  return const_iterator();
483 
484  return const_iterator( &d->fields.first() );
485 }
486 
487 QgsFields::const_iterator QgsFields::constEnd() const noexcept
488 {
489  if ( d->fields.isEmpty() )
490  return const_iterator();
491 
492  return const_iterator( &d->fields.last() + 1 );
493 }
494 
495 QgsFields::const_iterator QgsFields::begin() const noexcept
496 {
497  if ( d->fields.isEmpty() )
498  return const_iterator();
499 
500  return const_iterator( &d->fields.first() );
501 }
502 
503 QgsFields::const_iterator QgsFields::end() const noexcept
504 {
505  if ( d->fields.isEmpty() )
506  return const_iterator();
507 
508  return const_iterator( &d->fields.last() + 1 );
509 }
510 
511 QgsFields::iterator QgsFields::begin()
512 {
513  if ( d->fields.isEmpty() )
514  return iterator();
515 
516  d.detach();
517  return iterator( &d->fields.first() );
518 }
519 
520 QgsFields::iterator QgsFields::end()
521 {
522  if ( d->fields.isEmpty() )
523  return iterator();
524 
525  d.detach();
526  return iterator( &d->fields.last() + 1 );
527 }
528 
529 QIcon QgsFields::iconForField( int fieldIdx ) const
530 {
531  switch ( d->fields.at( fieldIdx ).field.type() )
532  {
533  case QVariant::Int:
534  case QVariant::UInt:
535  case QVariant::LongLong:
536  case QVariant::ULongLong:
537  {
538  return QgsApplication::getThemeIcon( "/mIconFieldInteger.svg" );
539  }
540  case QVariant::Double:
541  {
542  return QgsApplication::getThemeIcon( "/mIconFieldFloat.svg" );
543  }
544  case QVariant::String:
545  {
546  return QgsApplication::getThemeIcon( "/mIconFieldText.svg" );
547  }
548  case QVariant::Date:
549  {
550  return QgsApplication::getThemeIcon( "/mIconFieldDate.svg" );
551  }
552  case QVariant::DateTime:
553  {
554  return QgsApplication::getThemeIcon( "/mIconFieldDateTime.svg" );
555  }
556  case QVariant::Time:
557  {
558  return QgsApplication::getThemeIcon( "/mIconFieldTime.svg" );
559  }
560  default:
561  return QIcon();
562  }
563 }
564 
565 /***************************************************************************
566  * This class is considered CRITICAL and any change MUST be accompanied with
567  * full unit tests in testqgsfields.cpp.
568  * See details in QEP #17
569  ****************************************************************************/
570 
571 int QgsFields::fieldNameIndex( const QString& fieldName ) const
572 {
573  for ( int idx = 0; idx < count(); ++idx )
574  {
575  if ( d->fields[idx].field.name() == fieldName )
576  return idx;
577  }
578 
579  for ( int idx = 0; idx < count(); ++idx )
580  {
581  if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
582  return idx;
583  }
584 
585  return -1;
586 }
587 
589 {
590  QgsAttributeList lst;
591  for ( int i = 0; i < d->fields.count(); ++i )
592  lst.append( i );
593  return lst;
594 }
595 
596 /***************************************************************************
597  * This class is considered CRITICAL and any change MUST be accompanied with
598  * full unit tests in testqgsfields.cpp.
599  * See details in QEP #17
600  ****************************************************************************/
601 
603 {
604  out << static_cast< quint32 >( fields.size() );
605  for ( int i = 0; i < fields.size(); i++ )
606  {
607  out << fields.field( i );
608  }
609  return out;
610 }
611 
613 {
614  fields.clear();
615  quint32 size;
616  in >> size;
617  for ( quint32 i = 0; i < size; i++ )
618  {
619  QgsField field;
620  in >> field;
621  fields.append( field );
622  }
623  return in;
624 }
bool canConvert(Type t) const
qlonglong toLongLong(bool *ok) const
bool isNumeric() const
Returns if this field is numeric.
QgsField & operator=(const QgsField &other)
Assignment operator.
Definition: qgsfield.cpp:64
QString comment() const
Returns the field comment.
int size() const
Return number of items.
Definition: qgsfield.cpp:407
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:448
QString name
Definition: qgsfield.h:52
struct QgsFields::Field Field
int precision
Definition: qgsfield.h:50
QString alias() const
Returns the alias for the field (the friendly displayed name of the field ), or an empty string if th...
QgsFields()
Constructor for an empty field container.
Definition: qgsfield.cpp:313
virtual ~QgsField()
Destructor.
Definition: qgsfield.cpp:70
QString alias
Definition: qgsfield.h:53
QgsFields & operator=(const QgsFields &other)
Assignment operator.
Definition: qgsfield.cpp:323
const_iterator constEnd() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qgsfield.cpp:487
QIcon iconForField(int fieldIdx) const
Returns an icon corresponding to a field index, based on the field&#39;s type and source.
Definition: qgsfield.cpp:529
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:152
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:412
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
QgsField(const QString &name=QString(), QVariant::Type type=QVariant::Invalid, const QString &typeName=QString(), int len=0, int prec=0, const QString &comment=QString())
Constructor.
Definition: qgsfield.cpp:46
QString comment
Definition: qgsfield.h:51
QDataStream & operator>>(QDataStream &in, QgsField &field)
Reads a field from stream in into field.
Definition: qgsfield.cpp:288
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:208
Container of fields for a vector layer.
Definition: qgsfield.h:252
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:133
bool appendExpressionField(const QgsField &field, int originIndex)
Append an expression field. The field must have unique name, otherwise it is rejected (returns false)...
Definition: qgsfield.cpp:359
void extend(const QgsFields &other)
Extend with fields from another QgsFields container.
Definition: qgsfield.cpp:383
int precision() const
Gets the precision of the field.
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:259
const QgsField & operator[](int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:443
bool operator==(const QgsFields &other) const
Definition: qgsfield.cpp:474
const_iterator end() const noexcept
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qgsfield.cpp:503
int count() const
Return number of items.
Definition: qgsfield.cpp:402
QString name() const
Returns the name of the field.
it has not been specified where the field comes from
Definition: qgsfield.h:258
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:422
int length
Definition: qgsfield.h:49
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:456
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:148
const char * name() const
double qgsRound(double x)
A round function which returns a double to guard against overflows.
Definition: qgis.h:386
QString number(int n, int base)
void append(const T &value)
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:588
int toInt(bool *ok) const
bool isNull() const
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:102
QString defaultValueExpression
Definition: qgsfield.h:54
void clear()
Remove all fields.
Definition: qgsfield.cpp:334
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:89
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:143
bool operator!=(const QgsField &other) const
Definition: qgsfield.cpp:79
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfield.cpp:346
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:188
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:370
void setDefaultValueExpression(const QString &expression)
Sets an expression to use when calculating the default value for the field.
Definition: qgsfield.cpp:167
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:571
const_iterator begin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfield.cpp:495
virtual ~QgsFields()
Definition: qgsfield.cpp:329
QVariant value(const QString &key, const QVariant &defaultValue) const
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:461
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:138
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfield.cpp:479
bool operator==(const QgsField &other) const
Definition: qgsfield.cpp:74
QString defaultValueExpression() const
Returns the expression used when calculating the default value for the field.
void setAlias(const QString &alias)
Sets the alias for the field (the friendly displayed name of the field ).
Definition: qgsfield.cpp:177
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:466
int length() const
Gets the length of the field.
int length() const
bool isEmpty() const
Check whether the container is empty.
Definition: qgsfield.cpp:397
QString left(int n) const
double toDouble(bool *ok) const
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:427
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:97
int compare(const QString &other) const
field is calculated from an expression
Definition: qgsfield.h:262
bool convert(Type t)
QString toString() const
void setComment(const QString &comment)
Set the field comment.
Definition: qgsfield.cpp:157
QDataStream & operator<<(QDataStream &out, const QgsField &field)
Writes the field to stream out.
Definition: qgsfield.cpp:275