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