QGIS API Documentation  2.13.0-Master
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 
21 #include <QSettings>
22 #include <QDataStream>
23 #include <QtCore/qmath.h>
24 
25 /***************************************************************************
26  * This class is considered CRITICAL and any change MUST be accompanied with
27  * full unit tests in testqgsfield.cpp.
28  * See details in QEP #17
29  ****************************************************************************/
30 
31 #if 0
32 QgsField::QgsField( QString nam, QString typ, int len, int prec, bool num,
33  QString comment )
34  : mName( nam ), mType( typ ), mLength( len ), mPrecision( prec ), mNumeric( num )
35  , mComment( comment )
36 {
37  // This function used to lower case the field name since some stores
38  // use upper case (eg. shapefiles), but that caused problems with
39  // attribute actions getting confused between uppercase and
40  // lowercase versions of the attribute names, so just leave the
41  // names how they are now.
42 }
43 #endif
44 QgsField::QgsField( const QString& name, QVariant::Type type,
45  const QString& typeName, int len, int prec, const QString& comment )
46 {
47  d = new QgsFieldPrivate( name, type, typeName, len, prec, comment );
48 }
49 
51  : d( other.d )
52 {
53 
54 }
55 
56 /***************************************************************************
57  * This class is considered CRITICAL and any change MUST be accompanied with
58  * full unit tests in testqgsfield.cpp.
59  * See details in QEP #17
60  ****************************************************************************/
61 
63 {
64  d = other.d;
65  return *this;
66 }
67 
69 {
70 }
71 
72 bool QgsField::operator==( const QgsField& other ) const
73 {
74  return *( other.d ) == *d;
75 }
76 
77 bool QgsField::operator!=( const QgsField& other ) const
78 {
79  return !( *this == other );
80 }
81 
83 {
84  return d->name;
85 }
86 
87 QVariant::Type QgsField::type() const
88 {
89  return d->type;
90 }
91 
93 {
94  return d->typeName;
95 }
96 
97 int QgsField::length() const
98 {
99  return d->length;
100 }
101 
103 {
104  return d->precision;
105 }
106 
108 {
109  return d->comment;
110 }
111 
112 /***************************************************************************
113  * This class is considered CRITICAL and any change MUST be accompanied with
114  * full unit tests in testqgsfield.cpp.
115  * See details in QEP #17
116  ****************************************************************************/
117 
118 void QgsField::setName( const QString& name )
119 {
120  d->name = name;
121 }
122 
123 void QgsField::setType( QVariant::Type type )
124 {
125  d->type = type;
126 }
127 
128 void QgsField::setTypeName( const QString& typeName )
129 {
130  d->typeName = typeName;
131 }
132 
133 void QgsField::setLength( int len )
134 {
135  d->length = len;
136 }
137 void QgsField::setPrecision( int precision )
138 {
139  d->precision = precision;
140 }
141 
142 void QgsField::setComment( const QString& comment )
143 {
144  d->comment = comment;
145 }
146 
147 /***************************************************************************
148  * This class is considered CRITICAL and any change MUST be accompanied with
149  * full unit tests in testqgsfield.cpp.
150  * See details in QEP #17
151  ****************************************************************************/
152 
154 {
155  if ( v.isNull() )
156  {
157  QSettings settings;
158  return settings.value( "qgis/nullValue", "NULL" ).toString();
159  }
160 
161  if ( d->type == QVariant::Double && d->precision > 0 )
162  return QString::number( v.toDouble(), 'f', d->precision );
163 
164  return v.toString();
165 }
166 
167 /***************************************************************************
168  * This class is considered CRITICAL and any change MUST be accompanied with
169  * full unit tests in testqgsfield.cpp.
170  * See details in QEP #17
171  ****************************************************************************/
172 
174 {
175  if ( v.isNull() )
176  {
177  v.convert( d->type );
178  return true;
179  }
180 
181  if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
182  {
183  v = QVariant( d->type );
184  return false;
185  }
186 
187  //String representations of doubles in QVariant will return false to convert( QVariant::Int )
188  //work around this by first converting to double, and then checking whether the double is convertible to int
189  if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
190  {
191  bool ok = false;
192  double dbl = v.toDouble( &ok );
193  if ( !ok )
194  {
195  //couldn't convert to number
196  v = QVariant( d->type );
197  return false;
198  }
199 
200  double round = qgsRound( dbl );
201  if ( round > INT_MAX || round < -INT_MAX )
202  {
203  //double too large to fit in int
204  v = QVariant( d->type );
205  return false;
206  }
207  v = QVariant( qRound( dbl ) );
208  return true;
209  }
210 
211  if ( !v.convert( d->type ) )
212  {
213  v = QVariant( d->type );
214  return false;
215  }
216 
217  if ( d->type == QVariant::Double && d->precision > 0 )
218  {
219  double s = qPow( 10, d->precision );
220  double d = v.toDouble() * s;
221  v = QVariant(( d < 0 ? ceil( d - 0.5 ) : floor( d + 0.5 ) ) / s );
222  return true;
223  }
224 
225  if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
226  {
227  v = v.toString().left( d->length );
228  return false;
229  }
230 
231  return true;
232 }
233 
234 /***************************************************************************
235  * This class is considered CRITICAL and any change MUST be accompanied with
236  * full unit tests in testqgsfield.cpp.
237  * See details in QEP #17
238  ****************************************************************************/
239 
241 {
242  out << field.name();
243  out << static_cast< quint32 >( field.type() );
244  out << field.typeName();
245  out << field.length();
246  out << field.precision();
247  out << field.comment();
248  return out;
249 }
250 
252 {
253  quint32 type, length, precision;
254  QString name, typeName, comment;
255  in >> name >> type >> typeName >> length >> precision >> comment;
256  field.setName( name );
257  field.setType( static_cast< QVariant::Type >( type ) );
258  field.setTypeName( typeName );
259  field.setLength( static_cast< int >( length ) );
260  field.setPrecision( static_cast< int >( precision ) );
261  field.setComment( comment );
262  return in;
263 }
264 
266 
267 
268 /***************************************************************************
269  * This class is considered CRITICAL and any change MUST be accompanied with
270  * full unit tests in testqgsfields.cpp.
271  * See details in QEP #17
272  ****************************************************************************/
273 
275 {
276  d = new QgsFieldsPrivate( );
277 }
278 
280  : d( other.d )
281 {
282 }
283 
285 {
286  d = other.d;
287  return *this;
288 }
289 
291 {
292 
293 }
294 
296 {
297  d->fields.clear();
298  d->nameToIndex.clear();
299 }
300 
301 /***************************************************************************
302  * This class is considered CRITICAL and any change MUST be accompanied with
303  * full unit tests in testqgsfields.cpp.
304  * See details in QEP #17
305  ****************************************************************************/
306 
307 bool QgsFields::append( const QgsField& field, FieldOrigin origin, int originIndex )
308 {
309  if ( d->nameToIndex.contains( field.name() ) )
310  return false;
311 
312  if ( originIndex == -1 && origin == OriginProvider )
313  originIndex = d->fields.count();
314  d->fields.append( Field( field, origin, originIndex ) );
315 
316  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
317  return true;
318 }
319 
320 bool QgsFields::appendExpressionField( const QgsField& field, int originIndex )
321 {
322  if ( d->nameToIndex.contains( field.name() ) )
323  return false;
324 
325  d->fields.append( Field( field, OriginExpression, originIndex ) );
326 
327  d->nameToIndex.insert( field.name(), d->fields.count() - 1 );
328  return true;
329 }
330 
331 void QgsFields::remove( int fieldIdx )
332 {
333  if ( !exists( fieldIdx ) )
334  return;
335 
336  d->fields.remove( fieldIdx );
337  d->nameToIndex.clear();
338  for ( int idx = 0; idx < count(); ++idx )
339  {
340  d->nameToIndex.insert( d->fields.at( idx ).field.name(), idx );
341  }
342 }
343 
344 void QgsFields::extend( const QgsFields& other )
345 {
346  for ( int i = 0; i < other.count(); ++i )
347  {
348  append( other.at( i ), other.fieldOrigin( i ), other.fieldOriginIndex( i ) );
349  }
350 }
351 
352 /***************************************************************************
353  * This class is considered CRITICAL and any change MUST be accompanied with
354  * full unit tests in testqgsfields.cpp.
355  * See details in QEP #17
356  ****************************************************************************/
357 
358 bool QgsFields::isEmpty() const
359 {
360  return d->fields.isEmpty();
361 }
362 
363 int QgsFields::count() const
364 {
365  return d->fields.count();
366 }
367 
368 int QgsFields::size() const
369 {
370  return d->fields.count();
371 }
372 
373 bool QgsFields::exists( int i ) const
374 {
375  return i >= 0 && i < d->fields.count();
376 }
377 
379 {
380  return d->fields[i].field;
381 }
382 
383 const QgsField &QgsFields::at( int i ) const
384 {
385  return d->fields[i].field;
386 }
387 
388 const QgsField &QgsFields::field( int fieldIdx ) const
389 {
390  return d->fields[fieldIdx].field;
391 }
392 
393 const QgsField &QgsFields::field( const QString &name ) const
394 {
395  return d->fields[ indexFromName( name )].field;
396 }
397 
398 /***************************************************************************
399  * This class is considered CRITICAL and any change MUST be accompanied with
400  * full unit tests in testqgsfields.cpp.
401  * See details in QEP #17
402  ****************************************************************************/
403 
404 const QgsField &QgsFields::operator[]( int i ) const
405 {
406  return d->fields[i].field;
407 }
408 
410 {
411  if ( !exists( fieldIdx ) )
412  return OriginUnknown;
413 
414  return d->fields[fieldIdx].origin;
415 }
416 
417 int QgsFields::fieldOriginIndex( int fieldIdx ) const
418 {
419  return d->fields[fieldIdx].originIndex;
420 }
421 
422 int QgsFields::indexFromName( const QString &name ) const
423 {
424  return d->nameToIndex.value( name, -1 );
425 }
426 
428 {
429  QList<QgsField> lst;
430  for ( int i = 0; i < d->fields.count(); ++i )
431  lst.append( d->fields[i].field );
432  return lst;
433 }
434 
435 bool QgsFields::operator==( const QgsFields &other ) const
436 {
437  return d->fields == other.d->fields;
438 }
439 
440 /***************************************************************************
441  * This class is considered CRITICAL and any change MUST be accompanied with
442  * full unit tests in testqgsfields.cpp.
443  * See details in QEP #17
444  ****************************************************************************/
445 
446 int QgsFields::fieldNameIndex( const QString& fieldName ) const
447 {
448  for ( int idx = 0; idx < count(); ++idx )
449  {
450  if ( d->fields[idx].field.name() == fieldName )
451  return idx;
452  }
453 
454  for ( int idx = 0; idx < count(); ++idx )
455  {
456  if ( QString::compare( d->fields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
457  return idx;
458  }
459 
460  return -1;
461 }
462 
464 {
465  QgsAttributeList lst;
466  for ( int i = 0; i < d->fields.count(); ++i )
467  lst.append( i );
468  return lst;
469 }
470 
471 /***************************************************************************
472  * This class is considered CRITICAL and any change MUST be accompanied with
473  * full unit tests in testqgsfields.cpp.
474  * See details in QEP #17
475  ****************************************************************************/
476 
478 {
479  out << static_cast< quint32 >( fields.size() );
480  for ( int i = 0; i < fields.size(); i++ )
481  {
482  out << fields.field( i );
483  }
484  return out;
485 }
486 
488 {
489  fields.clear();
490  quint32 size;
491  in >> size;
492  for ( quint32 i = 0; i < size; i++ )
493  {
494  QgsField field;
495  in >> field;
496  fields.append( field );
497  }
498  return in;
499 }
QList< QgsField > toList() const
Utility function to return a list of QgsField instances.
Definition: qgsfield.cpp:427
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:404
QgsField & operator=(const QgsField &other)
Assignment operator.
Definition: qgsfield.cpp:62
bool operator==(const QgsField &other) const
Definition: qgsfield.cpp:72
const QgsField & field(int fieldIdx) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:388
struct QgsFields::Field Field
QgsFields()
Constructor for an empty field container.
Definition: qgsfield.cpp:274
virtual ~QgsField()
Destructor.
Definition: qgsfield.cpp:68
QgsFields & operator=(const QgsFields &other)
Assignment operator.
Definition: qgsfield.cpp:284
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:153
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:137
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:446
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:44
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:102
QDataStream & operator>>(QDataStream &in, QgsField &field)
Reads a field from stream in into field.
Definition: qgsfield.cpp:251
Container of fields for a vector layer.
Definition: qgsfield.h:189
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:118
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:320
void extend(const QgsFields &other)
Extend with fields from another QgsFields container.
Definition: qgsfield.cpp:344
QString comment() const
Returns the field comment.
Definition: qgsfield.cpp:107
field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfield.h:196
it has not been specified where the field comes from
Definition: qgsfield.h:195
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:133
double qgsRound(double x)
Definition: qgis.h:312
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:373
QString number(int n, int base)
void append(const T &value)
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:92
int toInt(bool *ok) const
bool isNull() const
void clear()
Remove all fields.
Definition: qgsfield.cpp:295
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:128
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:82
bool operator!=(const QgsField &other) const
Definition: qgsfield.cpp:77
int fieldOriginIndex(int fieldIdx) const
Get field's origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:417
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:307
int count() const
Return number of items.
Definition: qgsfield.cpp:363
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:383
void remove(int fieldIdx)
Remove a field with the given index.
Definition: qgsfield.cpp:331
int indexFromName(const QString &name) const
Look up field's index from name. Returns -1 on error.
Definition: qgsfield.cpp:422
virtual ~QgsFields()
Definition: qgsfield.cpp:290
QVariant value(const QString &key, const QVariant &defaultValue) const
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:123
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:173
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:97
int size() const
Return number of items.
Definition: qgsfield.cpp:368
FieldOrigin fieldOrigin(int fieldIdx) const
Get field's origin (value from an enumeration)
Definition: qgsfield.cpp:409
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:358
int compare(const QString &other) const
field is calculated from an expression
Definition: qgsfield.h:199
bool convert(Type t)
QString toString() const
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:463
void setComment(const QString &comment)
Set the field comment.
Definition: qgsfield.cpp:142
QDataStream & operator<<(QDataStream &out, const QgsField &field)
Writes the field to stream out.
Definition: qgsfield.cpp:240
bool operator==(const QgsFields &other) const
Definition: qgsfield.cpp:435
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:87