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