QGIS API Documentation  3.2.0-Bonn (bc43194)
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 "qgsfields.h"
18 #include "qgsfield_p.h"
19 #include "qgis.h"
20 #include "qgsapplication.h"
21 #include "qgssettings.h"
22 
23 #include <QDataStream>
24 #include <QIcon>
25 #include <QLocale>
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 (e.g., 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  QVariant::Type subType )
49 {
50  d = new QgsFieldPrivate( name, type, subType, typeName, len, prec, comment );
51 }
52 
53 QgsField::QgsField( const QgsField &other ) //NOLINT
54  : d( other.d )
55 {
56 
57 }
58 
59 /***************************************************************************
60  * This class is considered CRITICAL and any change MUST be accompanied with
61  * full unit tests in testqgsfield.cpp.
62  * See details in QEP #17
63  ****************************************************************************/
64 
65 QgsField &QgsField::operator =( const QgsField &other ) //NOLINT
66 {
67  d = other.d;
68  return *this;
69 }
70 
71 bool QgsField::operator==( const QgsField &other ) const
72 {
73  return *( other.d ) == *d;
74 }
75 
76 bool QgsField::operator!=( const QgsField &other ) const
77 {
78  return !( *this == other );
79 }
80 
81 QString QgsField::name() const
82 {
83  return d->name;
84 }
85 
86 QString QgsField::displayName() const
87 {
88  if ( !d->alias.isEmpty() )
89  return d->alias;
90  else
91  return d->name;
92 }
93 
94 QVariant::Type QgsField::type() const
95 {
96  return d->type;
97 }
98 
99 QVariant::Type QgsField::subType() const
100 {
101  return d->subType;
102 }
103 
104 QString QgsField::typeName() const
105 {
106  return d->typeName;
107 }
108 
109 int QgsField::length() const
110 {
111  return d->length;
112 }
113 
114 int QgsField::precision() const
115 {
116  return d->precision;
117 }
118 
119 QString QgsField::comment() const
120 {
121  return d->comment;
122 }
123 
124 bool QgsField::isNumeric() const
125 {
126  return d->type == QVariant::Double || d->type == QVariant::Int || d->type == QVariant::UInt || d->type == QVariant::LongLong || d->type == QVariant::ULongLong;
127 }
128 
129 /***************************************************************************
130  * This class is considered CRITICAL and any change MUST be accompanied with
131  * full unit tests in testqgsfield.cpp.
132  * See details in QEP #17
133  ****************************************************************************/
134 
135 void QgsField::setName( const QString &name )
136 {
137  d->name = name;
138 }
139 
140 void QgsField::setType( QVariant::Type type )
141 {
142  d->type = type;
143 }
144 
145 void QgsField::setSubType( QVariant::Type subType )
146 {
147  d->subType = subType;
148 }
149 
150 void QgsField::setTypeName( const QString &typeName )
151 {
152  d->typeName = typeName;
153 }
154 
155 void QgsField::setLength( int len )
156 {
157  d->length = len;
158 }
160 {
161  d->precision = precision;
162 }
163 
164 void QgsField::setComment( const QString &comment )
165 {
166  d->comment = comment;
167 }
168 
170 {
171  return d->defaultValueDefinition;
172 }
173 
175 {
176  d->defaultValueDefinition = defaultValueDefinition;
177 }
178 
180 {
181  d->constraints = constraints;
182 }
183 
185 {
186  return d->constraints;
187 }
188 
189 QString QgsField::alias() const
190 {
191  return d->alias;
192 }
193 
194 void QgsField::setAlias( const QString &alias )
195 {
196  d->alias = alias;
197 }
198 
199 /***************************************************************************
200  * This class is considered CRITICAL and any change MUST be accompanied with
201  * full unit tests in testqgsfield.cpp.
202  * See details in QEP #17
203  ****************************************************************************/
204 
205 QString QgsField::displayString( const QVariant &v ) const
206 {
207  if ( v.isNull() )
208  {
210  }
211 
212  // Special treatment for numeric types if group separator is set or decimalPoint is not a dot
213  if ( d->type == QVariant::Double )
214  {
215  // Locales with decimal point != '.' or that require group separator: use QLocale
216  if ( QLocale().decimalPoint() != '.' ||
217  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
218  {
219  if ( d->precision > 0 )
220  {
221  return QLocale().toString( v.toDouble(), 'f', d->precision );
222  }
223  else
224  {
225  // Precision is not set, let's guess it from the
226  // standard conversion to string
227  QString s( v.toString() );
228  int dotPosition( s.indexOf( '.' ) );
229  int precision;
230  if ( dotPosition < 0 )
231  {
232  precision = 0;
233  }
234  else
235  {
236  precision = s.length() - dotPosition - 1;
237  }
238  return QLocale().toString( v.toDouble(), 'f', precision );
239  }
240  }
241  // Default for doubles with precision
242  else if ( d->type == QVariant::Double && d->precision > 0 )
243  {
244  return QString::number( v.toDouble(), 'f', d->precision );
245  }
246  }
247  // Other numeric types than doubles
248  else if ( isNumeric() &&
249  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
250  {
251  bool ok;
252  qlonglong converted( v.toLongLong( &ok ) );
253  if ( ok )
254  return QLocale().toString( converted );
255  }
256  // Fallback if special rules do not apply
257  return v.toString();
258 }
259 
260 /***************************************************************************
261  * This class is considered CRITICAL and any change MUST be accompanied with
262  * full unit tests in testqgsfield.cpp.
263  * See details in QEP #17
264  ****************************************************************************/
265 
266 bool QgsField::convertCompatible( QVariant &v ) const
267 {
268  if ( v.isNull() )
269  {
270  v.convert( d->type );
271  return true;
272  }
273 
274  if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
275  {
276  v = QVariant( d->type );
277  return false;
278  }
279 
280  // Give it a chance to convert to double since for not '.' locales
281  // we accept both comma and dot as decimal point
282  if ( d->type == QVariant::Double && v.type() == QVariant::String )
283  {
284  QVariant tmp( v );
285  if ( !tmp.convert( d->type ) )
286  {
287  // This might be a string with thousand separator: use locale to convert
288  bool ok;
289  double d = QLocale().toDouble( v.toString(), &ok );
290  if ( ok )
291  {
292  v = QVariant( d );
293  return true;
294  }
295  // For not 'dot' locales, we also want to accept '.'
296  if ( QLocale().decimalPoint() != '.' )
297  {
298  d = QLocale( QLocale::English ).toDouble( v.toString(), &ok );
299  if ( ok )
300  {
301  v = QVariant( d );
302  return true;
303  }
304  }
305  }
306  }
307 
308  // For string representation of an int we also might have thousand separator
309  if ( d->type == QVariant::Int && v.type() == QVariant::String )
310  {
311  QVariant tmp( v );
312  if ( !tmp.convert( d->type ) )
313  {
314  // This might be a string with thousand separator: use locale to convert
315  bool ok;
316  int i = QLocale().toInt( v.toString(), &ok );
317  if ( ok )
318  {
319  v = QVariant( i );
320  return true;
321  }
322  }
323  }
324 
325  // For string representation of a long we also might have thousand separator
326  if ( d->type == QVariant::LongLong && v.type() == QVariant::String )
327  {
328  QVariant tmp( v );
329  if ( !tmp.convert( d->type ) )
330  {
331  // This might be a string with thousand separator: use locale to convert
332  bool ok;
333  qlonglong l = QLocale().toLongLong( v.toString(), &ok );
334  if ( ok )
335  {
336  v = QVariant( l );
337  return true;
338  }
339  }
340  }
341 
342  //String representations of doubles in QVariant will return false to convert( QVariant::Int )
343  //work around this by first converting to double, and then checking whether the double is convertible to int
344  if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
345  {
346  bool ok = false;
347  double dbl = v.toDouble( &ok );
348  if ( !ok )
349  {
350  //couldn't convert to number
351  v = QVariant( d->type );
352  return false;
353  }
354 
355  double round = std::round( dbl );
356  if ( round > std::numeric_limits<int>::max() || round < -std::numeric_limits<int>::max() )
357  {
358  //double too large to fit in int
359  v = QVariant( d->type );
360  return false;
361  }
362  v = QVariant( static_cast< int >( std::round( dbl ) ) );
363  return true;
364  }
365 
366 
367  if ( !v.convert( d->type ) )
368  {
369  v = QVariant( d->type );
370  return false;
371  }
372 
373  if ( d->type == QVariant::Double && d->precision > 0 )
374  {
375  double s = std::pow( 10, d->precision );
376  double d = v.toDouble() * s;
377  v = QVariant( ( d < 0 ? std::ceil( d - 0.5 ) : std::floor( d + 0.5 ) ) / s );
378  return true;
379  }
380 
381  if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
382  {
383  v = v.toString().left( d->length );
384  return false;
385  }
386 
387  return true;
388 }
389 
391 {
392  d->editorWidgetSetup = v;
393 }
394 
396 {
397  return d->editorWidgetSetup;
398 }
399 
400 /***************************************************************************
401  * This class is considered CRITICAL and any change MUST be accompanied with
402  * full unit tests in testqgsfield.cpp.
403  * See details in QEP #17
404  ****************************************************************************/
405 
406 QDataStream &operator<<( QDataStream &out, const QgsField &field )
407 {
408  out << field.name();
409  out << static_cast< quint32 >( field.type() );
410  out << field.typeName();
411  out << field.length();
412  out << field.precision();
413  out << field.comment();
414  out << field.alias();
415  out << field.defaultValueDefinition().expression();
416  out << field.defaultValueDefinition().applyOnUpdate();
417  out << field.constraints().constraints();
418  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintNotNull ) );
419  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintUnique ) );
420  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintExpression ) );
421  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
422  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
423  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
424  out << field.constraints().constraintExpression();
425  out << field.constraints().constraintDescription();
426  out << static_cast< quint32 >( field.subType() );
427  return out;
428 }
429 
430 QDataStream &operator>>( QDataStream &in, QgsField &field )
431 {
432  quint32 type;
433  quint32 subType;
434  quint32 length;
435  quint32 precision;
436  quint32 constraints;
437  quint32 originNotNull;
438  quint32 originUnique;
439  quint32 originExpression;
440  quint32 strengthNotNull;
441  quint32 strengthUnique;
442  quint32 strengthExpression;
443 
444  bool applyOnUpdate;
445 
446  QString name;
447  QString typeName;
448  QString comment;
449  QString alias;
450  QString defaultValueExpression;
451  QString constraintExpression;
452  QString constraintDescription;
453 
454  in >> name >> type >> typeName >> length >> precision >> comment >> alias
455  >> defaultValueExpression >> applyOnUpdate >> constraints >> originNotNull >> originUnique >> originExpression >> strengthNotNull >> strengthUnique >> strengthExpression >>
456  constraintExpression >> constraintDescription >> subType;
457  field.setName( name );
458  field.setType( static_cast< QVariant::Type >( type ) );
459  field.setTypeName( typeName );
460  field.setLength( static_cast< int >( length ) );
461  field.setPrecision( static_cast< int >( precision ) );
462  field.setComment( comment );
463  field.setAlias( alias );
464  field.setDefaultValueDefinition( QgsDefaultValue( defaultValueExpression, applyOnUpdate ) );
465  QgsFieldConstraints fieldConstraints;
466  if ( constraints & QgsFieldConstraints::ConstraintNotNull )
467  {
468  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintOrigin>( originNotNull ) );
469  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthNotNull ) );
470  }
471  else
472  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintNotNull );
473  if ( constraints & QgsFieldConstraints::ConstraintUnique )
474  {
475  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintOrigin>( originUnique ) );
476  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthUnique ) );
477  }
478  else
479  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintUnique );
480  if ( constraints & QgsFieldConstraints::ConstraintExpression )
481  {
482  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintOrigin>( originExpression ) );
483  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthExpression ) );
484  }
485  else
486  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintExpression );
487  fieldConstraints.setConstraintExpression( constraintExpression, constraintDescription );
488  field.setConstraints( fieldConstraints );
489  field.setSubType( static_cast< QVariant::Type >( subType ) );
490  return in;
491 }
bool isNumeric() const
Returns if this field is numeric.
QgsField & operator=(const QgsField &other)
Assignment operator.
Definition: qgsfield.cpp:65
void setConstraintStrength(Constraint constraint, ConstraintStrength strength)
Sets the strength of a constraint.
QgsField(const QString &name=QString(), QVariant::Type type=QVariant::Invalid, const QString &typeName=QString(), int len=0, int prec=0, const QString &comment=QString(), QVariant::Type subType=QVariant::Invalid)
Constructor.
Definition: qgsfield.cpp:46
QString comment() const
Returns the field comment.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
QString name
Definition: qgsfield.h:57
int precision
Definition: qgsfield.h:54
QString alias() const
Returns the alias for the field (the friendly displayed name of the field ), or an empty string if th...
QString alias
Definition: qgsfield.h:58
The QgsDefaultValue class provides a container for managing client side default values for fields...
void setPrecision(int precision)
Set the field precision.
Definition: qgsfield.cpp:159
QString comment
Definition: qgsfield.h:56
QDataStream & operator>>(QDataStream &in, QgsField &field)
Reads a field from stream in into field. QGIS version compatibility is not guaranteed.
Definition: qgsfield.cpp:430
void setDefaultValueDefinition(const QgsDefaultValue &defaultValueDefinition)
Sets an expression to use when calculating the default value for the field.
Definition: qgsfield.cpp:174
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:266
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:135
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:395
int precision() const
Gets the precision of the field.
Stores information about constraints which may be present on a field.
QString name() const
Returns the name of the field.
Field has an expression constraint set. See constraintExpression().
int length
Definition: qgsfield.h:53
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:155
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:104
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:86
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:150
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
bool operator!=(const QgsField &other) const
Definition: qgsfield.cpp:76
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:205
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
void setSubType(QVariant::Type subType)
If the field is a collection, set its element&#39;s type.
Definition: qgsfield.cpp:145
QgsFieldConstraints constraints
Definition: qgsfield.h:60
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:140
bool operator==(const QgsField &other) const
Definition: qgsfield.cpp:71
void setAlias(const QString &alias)
Sets the alias for the field (the friendly displayed name of the field ).
Definition: qgsfield.cpp:194
void setConstraintExpression(const QString &expression, const QString &description=QString())
Set the constraint expression for the field.
Holder for the widget type and its configuration for a field.
int length() const
Gets the length of the field.
QVariant::Type subType() const
If the field is a collection, gets its element&#39;s type.
Definition: qgsfield.cpp:99
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
const QgsFieldConstraints & constraints() const
Returns constraints which are present for the field.
QString constraintExpression() const
Returns the constraint expression for the field, if set.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
void setConstraints(const QgsFieldConstraints &constraints)
Sets constraints which are present for the field.
Definition: qgsfield.cpp:179
void setComment(const QString &comment)
Set the field comment.
Definition: qgsfield.cpp:164
QVariant::Type type
Definition: qgsfield.h:55
QDataStream & operator<<(QDataStream &out, const QgsField &field)
Writes the field to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsfield.cpp:406
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:59
void removeConstraint(Constraint constraint)
Removes a constraint from the field.
QgsDefaultValue defaultValueDefinition() const
Returns the expression used when calculating the default value for the field.
Field must have a unique value.
void setEditorWidgetSetup(const QgsEditorWidgetSetup &v)
Set the editor widget setup for the field.
Definition: qgsfield.cpp:390