QGIS API Documentation  2.17.0-Master (973e4b0)
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 
89 QVariant::Type QgsField::type() const
90 {
91  return d->type;
92 }
93 
95 {
96  return d->typeName;
97 }
98 
99 int QgsField::length() const
100 {
101  return d->length;
102 }
103 
104 int QgsField::precision() const
105 {
106  return d->precision;
107 }
108 
110 {
111  return d->comment;
112 }
113 
114 bool QgsField::isNumeric() const
115 {
116  return d->type == QVariant::Double || d->type == QVariant::Int || d->type == QVariant::UInt || d->type == QVariant::LongLong || d->type == QVariant::ULongLong;
117 }
118 
119 /***************************************************************************
120  * This class is considered CRITICAL and any change MUST be accompanied with
121  * full unit tests in testqgsfield.cpp.
122  * See details in QEP #17
123  ****************************************************************************/
124 
126 {
127  d->name = name;
128 }
129 
130 void QgsField::setType( QVariant::Type type )
131 {
132  d->type = type;
133 }
134 
136 {
137  d->typeName = typeName;
138 }
139 
140 void QgsField::setLength( int len )
141 {
142  d->length = len;
143 }
145 {
146  d->precision = precision;
147 }
148 
150 {
151  d->comment = comment;
152 }
153 
154 /***************************************************************************
155  * This class is considered CRITICAL and any change MUST be accompanied with
156  * full unit tests in testqgsfield.cpp.
157  * See details in QEP #17
158  ****************************************************************************/
159 
161 {
162  if ( v.isNull() )
163  {
164  QSettings settings;
165  return settings.value( "qgis/nullValue", "NULL" ).toString();
166  }
167 
168  if ( d->type == QVariant::Double && d->precision > 0 )
169  return QString::number( v.toDouble(), 'f', d->precision );
170 
171  return v.toString();
172 }
173 
174 /***************************************************************************
175  * This class is considered CRITICAL and any change MUST be accompanied with
176  * full unit tests in testqgsfield.cpp.
177  * See details in QEP #17
178  ****************************************************************************/
179 
181 {
182  if ( v.isNull() )
183  {
184  v.convert( d->type );
185  return true;
186  }
187 
188  if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
189  {
190  v = QVariant( d->type );
191  return false;
192  }
193 
194  //String representations of doubles in QVariant will return false to convert( QVariant::Int )
195  //work around this by first converting to double, and then checking whether the double is convertible to int
196  if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
197  {
198  bool ok = false;
199  double dbl = v.toDouble( &ok );
200  if ( !ok )
201  {
202  //couldn't convert to number
203  v = QVariant( d->type );
204  return false;
205  }
206 
207  double round = qgsRound( dbl );
208  if ( round > INT_MAX || round < -INT_MAX )
209  {
210  //double too large to fit in int
211  v = QVariant( d->type );
212  return false;
213  }
214  v = QVariant( qRound( dbl ) );
215  return true;
216  }
217 
218  if ( !v.convert( d->type ) )
219  {
220  v = QVariant( d->type );
221  return false;
222  }
223 
224  if ( d->type == QVariant::Double && d->precision > 0 )
225  {
226  double s = qPow( 10, d->precision );
227  double d = v.toDouble() * s;
228  v = QVariant(( d < 0 ? ceil( d - 0.5 ) : floor( d + 0.5 ) ) / s );
229  return true;
230  }
231 
232  if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
233  {
234  v = v.toString().left( d->length );
235  return false;
236  }
237 
238  return true;
239 }
240 
241 /***************************************************************************
242  * This class is considered CRITICAL and any change MUST be accompanied with
243  * full unit tests in testqgsfield.cpp.
244  * See details in QEP #17
245  ****************************************************************************/
246 
248 {
249  out << field.name();
250  out << static_cast< quint32 >( field.type() );
251  out << field.typeName();
252  out << field.length();
253  out << field.precision();
254  out << field.comment();
255  return out;
256 }
257 
259 {
260  quint32 type, length, precision;
262  in >> name >> type >> typeName >> length >> precision >> comment;
263  field.setName( name );
264  field.setType( static_cast< QVariant::Type >( type ) );
265  field.setTypeName( typeName );
266  field.setLength( static_cast< int >( length ) );
267  field.setPrecision( static_cast< int >( precision ) );
268  field.setComment( comment );
269  return in;
270 }
271 
273 
274 
275 /***************************************************************************
276  * This class is considered CRITICAL and any change MUST be accompanied with
277  * full unit tests in testqgsfields.cpp.
278  * See details in QEP #17
279  ****************************************************************************/
280 
282 {
283  d = new QgsFieldsPrivate();
284 }
285 
287  : d( other.d )
288 {
289 }
290 
292 {
293  d = other.d;
294  return *this;
295 }
296 
298 {
299 
300 }
301 
303 {
304  d->fields.clear();
305  d->nameToIndex.clear();
306 }
307 
308 /***************************************************************************
309  * This class is considered CRITICAL and any change MUST be accompanied with
310  * full unit tests in testqgsfields.cpp.
311  * See details in QEP #17
312  ****************************************************************************/
313 
314 bool QgsFields::append( const QgsField& field, FieldOrigin origin, int originIndex )
315 {
316  if ( d->nameToIndex.contains( field.name() ) )
317  return false;
318 
319  if ( originIndex == -1 && origin == OriginProvider )
320  originIndex = d->fields.count();
321  d->fields.append( Field( field, origin, originIndex ) );
322 
323  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
324  return true;
325 }
326 
327 bool QgsFields::appendExpressionField( const QgsField& field, int originIndex )
328 {
329  if ( d->nameToIndex.contains( field.name() ) )
330  return false;
331 
332  d->fields.append( Field( field, OriginExpression, originIndex ) );
333 
334  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
335  return true;
336 }
337 
338 void QgsFields::remove( int fieldIdx )
339 {
340  if ( !exists( fieldIdx ) )
341  return;
342 
343  d->fields.remove( fieldIdx );
344  d->nameToIndex.clear();
345  for ( int idx = 0; idx < count(); ++idx )
346  {
347  d->nameToIndex.insert( d->fields.at( idx ).field.name(), idx );
348  }
349 }
350 
351 void QgsFields::extend( const QgsFields& other )
352 {
353  for ( int i = 0; i < other.count(); ++i )
354  {
355  append( other.at( i ), other.fieldOrigin( i ), other.fieldOriginIndex( i ) );
356  }
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 
365 bool QgsFields::isEmpty() const
366 {
367  return d->fields.isEmpty();
368 }
369 
370 int QgsFields::count() const
371 {
372  return d->fields.count();
373 }
374 
375 int QgsFields::size() const
376 {
377  return d->fields.count();
378 }
379 
380 bool QgsFields::exists( int i ) const
381 {
382  return i >= 0 && i < d->fields.count();
383 }
384 
386 {
387  return d->fields[i].field;
388 }
389 
390 const QgsField &QgsFields::at( int i ) const
391 {
392  return d->fields[i].field;
393 }
394 
395 const QgsField &QgsFields::field( int fieldIdx ) const
396 {
397  return d->fields[fieldIdx].field;
398 }
399 
400 const QgsField &QgsFields::field( const QString &name ) const
401 {
402  return d->fields[ indexFromName( name )].field;
403 }
404 
405 /***************************************************************************
406  * This class is considered CRITICAL and any change MUST be accompanied with
407  * full unit tests in testqgsfields.cpp.
408  * See details in QEP #17
409  ****************************************************************************/
410 
411 const QgsField &QgsFields::operator[]( int i ) const
412 {
413  return d->fields[i].field;
414 }
415 
417 {
418  if ( !exists( fieldIdx ) )
419  return OriginUnknown;
420 
421  return d->fields[fieldIdx].origin;
422 }
423 
424 int QgsFields::fieldOriginIndex( int fieldIdx ) const
425 {
426  return d->fields[fieldIdx].originIndex;
427 }
428 
429 int QgsFields::indexFromName( const QString &name ) const
430 {
431  return d->nameToIndex.value( name, -1 );
432 }
433 
435 {
436  QList<QgsField> lst;
437  for ( int i = 0; i < d->fields.count(); ++i )
438  lst.append( d->fields[i].field );
439  return lst;
440 }
441 
442 bool QgsFields::operator==( const QgsFields &other ) const
443 {
444  return d->fields == other.d->fields;
445 }
446 
447 QgsFields::const_iterator QgsFields::constBegin() const noexcept
448 {
449  if ( d->fields.isEmpty() )
450  return const_iterator();
451 
452  return const_iterator( &d->fields.first() );
453 }
454 
455 QgsFields::const_iterator QgsFields::constEnd() const noexcept
456 {
457  if ( d->fields.isEmpty() )
458  return const_iterator();
459 
460  return const_iterator( &d->fields.last() + 1 );
461 }
462 
463 QgsFields::const_iterator QgsFields::begin() const noexcept
464 {
465  if ( d->fields.isEmpty() )
466  return const_iterator();
467 
468  return const_iterator( &d->fields.first() );
469 }
470 
471 QgsFields::const_iterator QgsFields::end() const noexcept
472 {
473  if ( d->fields.isEmpty() )
474  return const_iterator();
475 
476  return const_iterator( &d->fields.last() + 1 );
477 }
478 
479 QgsFields::iterator QgsFields::begin()
480 {
481  if ( d->fields.isEmpty() )
482  return iterator();
483 
484  d.detach();
485  return iterator( &d->fields.first() );
486 }
487 
488 QgsFields::iterator QgsFields::end()
489 {
490  if ( d->fields.isEmpty() )
491  return iterator();
492 
493  d.detach();
494  return iterator( &d->fields.last() + 1 );
495 }
496 
497 QIcon QgsFields::iconForField( int fieldIdx ) const
498 {
499  switch ( d->fields.at( fieldIdx ).field.type() )
500  {
501  case QVariant::Int:
502  case QVariant::UInt:
503  case QVariant::LongLong:
504  case QVariant::ULongLong:
505  {
506  return QgsApplication::getThemeIcon( "/mIconFieldInteger.svg" );
507  }
508  case QVariant::Double:
509  {
510  return QgsApplication::getThemeIcon( "/mIconFieldFloat.svg" );
511  }
512  case QVariant::String:
513  {
514  return QgsApplication::getThemeIcon( "/mIconFieldText.svg" );
515  }
516  case QVariant::Date:
517  {
518  return QgsApplication::getThemeIcon( "/mIconFieldDate.svg" );
519  }
520  case QVariant::DateTime:
521  {
522  return QgsApplication::getThemeIcon( "/mIconFieldDateTime.svg" );
523  }
524  case QVariant::Time:
525  {
526  return QgsApplication::getThemeIcon( "/mIconFieldTime.svg" );
527  }
528  default:
529  return QIcon();
530  }
531 }
532 
533 /***************************************************************************
534  * This class is considered CRITICAL and any change MUST be accompanied with
535  * full unit tests in testqgsfields.cpp.
536  * See details in QEP #17
537  ****************************************************************************/
538 
539 int QgsFields::fieldNameIndex( const QString& fieldName ) const
540 {
541  for ( int idx = 0; idx < count(); ++idx )
542  {
543  if ( d->fields[idx].field.name() == fieldName )
544  return idx;
545  }
546 
547  for ( int idx = 0; idx < count(); ++idx )
548  {
549  if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
550  return idx;
551  }
552 
553  return -1;
554 }
555 
557 {
558  QgsAttributeList lst;
559  for ( int i = 0; i < d->fields.count(); ++i )
560  lst.append( i );
561  return lst;
562 }
563 
564 /***************************************************************************
565  * This class is considered CRITICAL and any change MUST be accompanied with
566  * full unit tests in testqgsfields.cpp.
567  * See details in QEP #17
568  ****************************************************************************/
569 
571 {
572  out << static_cast< quint32 >( fields.size() );
573  for ( int i = 0; i < fields.size(); i++ )
574  {
575  out << fields.field( i );
576  }
577  return out;
578 }
579 
581 {
582  fields.clear();
583  quint32 size;
584  in >> size;
585  for ( quint32 i = 0; i < size; i++ )
586  {
587  QgsField field;
588  in >> field;
589  fields.append( field );
590  }
591  return in;
592 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:434
bool canConvert(Type t) const
qlonglong toLongLong(bool *ok) const
const QgsField & operator[](int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:411
QgsField & operator=(const QgsField &other)
Assignment operator.
Definition: qgsfield.cpp:64
bool operator==(const QgsField &other) const
Definition: qgsfield.cpp:74
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:395
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:497
QString name
Definition: qgsfield.h:52
struct QgsFields::Field Field
int precision
Definition: qgsfield.h:50
QgsFields()
Constructor for an empty field container.
Definition: qgsfield.cpp:281
virtual ~QgsField()
Destructor.
Definition: qgsfield.cpp:70
QgsFields & operator=(const QgsFields &other)
Assignment operator.
Definition: qgsfield.cpp:291
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:455
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:160
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:144
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:539
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
int precision() const
Gets the precision of the field.
QDataStream & operator>>(QDataStream &in, QgsField &field)
Reads a field from stream in into field.
Definition: qgsfield.cpp:258
Container of fields for a vector layer.
Definition: qgsfield.h:209
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:125
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:327
void extend(const QgsFields &other)
Extend with fields from another QgsFields container.
Definition: qgsfield.cpp:351
QString comment() const
Returns the field comment.
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:216
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:471
it has not been specified where the field comes from
Definition: qgsfield.h:215
int length
Definition: qgsfield.h:49
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:140
double qgsRound(double x)
A round function which returns a double to guard against overflows.
Definition: qgis.h:386
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:380
QString number(int n, int base)
void append(const T &value)
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:94
int toInt(bool *ok) const
bool isNull() const
bool isNumeric() const
Returns if this field is numeric.
void clear()
Remove all fields.
Definition: qgsfield.cpp:302
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:135
QString name() const
Gets the name of the field.
bool operator!=(const QgsField &other) const
Definition: qgsfield.cpp:79
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:424
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:314
int count() const
Return number of items.
Definition: qgsfield.cpp:370
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:390
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:338
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:429
const_iterator begin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfield.cpp:463
virtual ~QgsFields()
Definition: qgsfield.cpp:297
QVariant value(const QString &key, const QVariant &defaultValue) const
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:130
const_iterator constBegin() const noexcept
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qgsfield.cpp:447
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:180
int length() const
Gets the length of the field.
int size() const
Return number of items.
Definition: qgsfield.cpp:375
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:416
int length() const
QString left(int n) const
double toDouble(bool *ok) const
bool isEmpty() const
Check whether the container is empty.
Definition: qgsfield.cpp:365
int compare(const QString &other) const
field is calculated from an expression
Definition: qgsfield.h:219
bool convert(Type t)
QString toString() const
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:556
void setComment(const QString &comment)
Set the field comment.
Definition: qgsfield.cpp:149
QDataStream & operator<<(QDataStream &out, const QgsField &field)
Writes the field to stream out.
Definition: qgsfield.cpp:247
bool operator==(const QgsFields &other) const
Definition: qgsfield.cpp:442
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:89