QGIS API Documentation  3.6.0-Noosa (5873452)
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 bool QgsField::isDateOrTime() const
131 {
132  return d->type == QVariant::Date || d->type == QVariant::Time || d->type == QVariant::DateTime;
133 }
134 
135 /***************************************************************************
136  * This class is considered CRITICAL and any change MUST be accompanied with
137  * full unit tests in testqgsfield.cpp.
138  * See details in QEP #17
139  ****************************************************************************/
140 
141 void QgsField::setName( const QString &name )
142 {
143  d->name = name;
144 }
145 
146 void QgsField::setType( QVariant::Type type )
147 {
148  d->type = type;
149 }
150 
151 void QgsField::setSubType( QVariant::Type subType )
152 {
153  d->subType = subType;
154 }
155 
156 void QgsField::setTypeName( const QString &typeName )
157 {
158  d->typeName = typeName;
159 }
160 
161 void QgsField::setLength( int len )
162 {
163  d->length = len;
164 }
166 {
167  d->precision = precision;
168 }
169 
170 void QgsField::setComment( const QString &comment )
171 {
172  d->comment = comment;
173 }
174 
176 {
177  return d->defaultValueDefinition;
178 }
179 
181 {
182  d->defaultValueDefinition = defaultValueDefinition;
183 }
184 
186 {
187  d->constraints = constraints;
188 }
189 
191 {
192  return d->constraints;
193 }
194 
195 QString QgsField::alias() const
196 {
197  return d->alias;
198 }
199 
200 void QgsField::setAlias( const QString &alias )
201 {
202  d->alias = alias;
203 }
204 
205 /***************************************************************************
206  * This class is considered CRITICAL and any change MUST be accompanied with
207  * full unit tests in testqgsfield.cpp.
208  * See details in QEP #17
209  ****************************************************************************/
210 
211 QString QgsField::displayString( const QVariant &v ) const
212 {
213  if ( v.isNull() )
214  {
216  }
217 
218  // Special treatment for numeric types if group separator is set or decimalPoint is not a dot
219  if ( d->type == QVariant::Double )
220  {
221  // Locales with decimal point != '.' or that require group separator: use QLocale
222  if ( QLocale().decimalPoint() != '.' ||
223  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
224  {
225  if ( d->precision > 0 )
226  {
227  return QLocale().toString( v.toDouble(), 'f', d->precision );
228  }
229  else
230  {
231  // Precision is not set, let's guess it from the
232  // standard conversion to string
233  QString s( v.toString() );
234  int dotPosition( s.indexOf( '.' ) );
235  int precision;
236  if ( dotPosition < 0 )
237  {
238  precision = 0;
239  }
240  else
241  {
242  precision = s.length() - dotPosition - 1;
243  }
244  return QLocale().toString( v.toDouble(), 'f', precision );
245  }
246  }
247  // Default for doubles with precision
248  else if ( d->type == QVariant::Double && d->precision > 0 )
249  {
250  return QString::number( v.toDouble(), 'f', d->precision );
251  }
252  }
253  // Other numeric types than doubles
254  else if ( isNumeric() &&
255  !( QLocale().numberOptions() & QLocale::NumberOption::OmitGroupSeparator ) )
256  {
257  bool ok;
258  qlonglong converted( v.toLongLong( &ok ) );
259  if ( ok )
260  return QLocale().toString( converted );
261  }
262  else if ( d->typeName.compare( QLatin1String( "json" ), Qt::CaseInsensitive ) == 0 || d->typeName == QLatin1String( "jsonb" ) )
263  {
264  QJsonDocument doc = QJsonDocument::fromVariant( v );
265  return QString::fromUtf8( doc.toJson().data() );
266  }
267  else if ( d->type == QVariant::ByteArray )
268  {
269  return QObject::tr( "BLOB" );
270  }
271  // Fallback if special rules do not apply
272  return v.toString();
273 }
274 
275 /***************************************************************************
276  * This class is considered CRITICAL and any change MUST be accompanied with
277  * full unit tests in testqgsfield.cpp.
278  * See details in QEP #17
279  ****************************************************************************/
280 
281 bool QgsField::convertCompatible( QVariant &v ) const
282 {
283  if ( v.isNull() )
284  {
285  v.convert( d->type );
286  return true;
287  }
288 
289  if ( d->type == QVariant::Int && v.toInt() != v.toLongLong() )
290  {
291  v = QVariant( d->type );
292  return false;
293  }
294 
295  // Give it a chance to convert to double since for not '.' locales
296  // we accept both comma and dot as decimal point
297  if ( d->type == QVariant::Double && v.type() == QVariant::String )
298  {
299  QVariant tmp( v );
300  if ( !tmp.convert( d->type ) )
301  {
302  // This might be a string with thousand separator: use locale to convert
303  bool ok = false;
304  double d = qgsPermissiveToDouble( v.toString(), ok );
305  if ( ok )
306  {
307  v = QVariant( d );
308  return true;
309  }
310  // For not 'dot' locales, we also want to accept '.'
311  if ( QLocale().decimalPoint() != '.' )
312  {
313  d = QLocale( QLocale::C ).toDouble( v.toString(), &ok );
314  if ( ok )
315  {
316  v = QVariant( d );
317  return true;
318  }
319  }
320  }
321  }
322 
323  // For string representation of an int we also might have thousand separator
324  if ( d->type == QVariant::Int && v.type() == QVariant::String )
325  {
326  QVariant tmp( v );
327  if ( !tmp.convert( d->type ) )
328  {
329  // This might be a string with thousand separator: use locale to convert
330  bool ok;
331  int i = qgsPermissiveToInt( v.toString(), ok );
332  if ( ok )
333  {
334  v = QVariant( i );
335  return true;
336  }
337  }
338  }
339 
340  // For string representation of a long we also might have thousand separator
341  if ( d->type == QVariant::LongLong && v.type() == QVariant::String )
342  {
343  QVariant tmp( v );
344  if ( !tmp.convert( d->type ) )
345  {
346  // This might be a string with thousand separator: use locale to convert
347  bool ok;
348  qlonglong l = qgsPermissiveToLongLong( v.toString(), ok );
349  if ( ok )
350  {
351  v = QVariant( l );
352  return true;
353  }
354  }
355  }
356 
357  //String representations of doubles in QVariant will return false to convert( QVariant::Int )
358  //work around this by first converting to double, and then checking whether the double is convertible to int
359  if ( d->type == QVariant::Int && v.canConvert( QVariant::Double ) )
360  {
361  bool ok = false;
362  double dbl = v.toDouble( &ok );
363  if ( !ok )
364  {
365  //couldn't convert to number
366  v = QVariant( d->type );
367  return false;
368  }
369 
370  double round = std::round( dbl );
371  if ( round > std::numeric_limits<int>::max() || round < -std::numeric_limits<int>::max() )
372  {
373  //double too large to fit in int
374  v = QVariant( d->type );
375  return false;
376  }
377  v = QVariant( static_cast< int >( std::round( dbl ) ) );
378  return true;
379  }
380 
381 
382  if ( !v.convert( d->type ) )
383  {
384  v = QVariant( d->type );
385  return false;
386  }
387 
388  if ( d->type == QVariant::Double && d->precision > 0 )
389  {
390  double s = std::pow( 10, d->precision );
391  double d = v.toDouble() * s;
392  v = QVariant( ( d < 0 ? std::ceil( d - 0.5 ) : std::floor( d + 0.5 ) ) / s );
393  return true;
394  }
395 
396  if ( d->type == QVariant::String && d->length > 0 && v.toString().length() > d->length )
397  {
398  v = v.toString().left( d->length );
399  return false;
400  }
401 
402  return true;
403 }
404 
406 {
407  d->editorWidgetSetup = v;
408 }
409 
411 {
412  return d->editorWidgetSetup;
413 }
414 
415 /***************************************************************************
416  * This class is considered CRITICAL and any change MUST be accompanied with
417  * full unit tests in testqgsfield.cpp.
418  * See details in QEP #17
419  ****************************************************************************/
420 
421 QDataStream &operator<<( QDataStream &out, const QgsField &field )
422 {
423  out << field.name();
424  out << static_cast< quint32 >( field.type() );
425  out << field.typeName();
426  out << field.length();
427  out << field.precision();
428  out << field.comment();
429  out << field.alias();
430  out << field.defaultValueDefinition().expression();
431  out << field.defaultValueDefinition().applyOnUpdate();
432  out << field.constraints().constraints();
433  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintNotNull ) );
434  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintUnique ) );
435  out << static_cast< quint32 >( field.constraints().constraintOrigin( QgsFieldConstraints::ConstraintExpression ) );
436  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
437  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
438  out << static_cast< quint32 >( field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
439  out << field.constraints().constraintExpression();
440  out << field.constraints().constraintDescription();
441  out << static_cast< quint32 >( field.subType() );
442  return out;
443 }
444 
445 QDataStream &operator>>( QDataStream &in, QgsField &field )
446 {
447  quint32 type;
448  quint32 subType;
449  quint32 length;
450  quint32 precision;
451  quint32 constraints;
452  quint32 originNotNull;
453  quint32 originUnique;
454  quint32 originExpression;
455  quint32 strengthNotNull;
456  quint32 strengthUnique;
457  quint32 strengthExpression;
458 
459  bool applyOnUpdate;
460 
461  QString name;
462  QString typeName;
463  QString comment;
464  QString alias;
465  QString defaultValueExpression;
466  QString constraintExpression;
467  QString constraintDescription;
468 
469  in >> name >> type >> typeName >> length >> precision >> comment >> alias
470  >> defaultValueExpression >> applyOnUpdate >> constraints >> originNotNull >> originUnique >> originExpression >> strengthNotNull >> strengthUnique >> strengthExpression >>
471  constraintExpression >> constraintDescription >> subType;
472  field.setName( name );
473  field.setType( static_cast< QVariant::Type >( type ) );
474  field.setTypeName( typeName );
475  field.setLength( static_cast< int >( length ) );
476  field.setPrecision( static_cast< int >( precision ) );
477  field.setComment( comment );
478  field.setAlias( alias );
479  field.setDefaultValueDefinition( QgsDefaultValue( defaultValueExpression, applyOnUpdate ) );
480  QgsFieldConstraints fieldConstraints;
481  if ( constraints & QgsFieldConstraints::ConstraintNotNull )
482  {
483  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintOrigin>( originNotNull ) );
484  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintNotNull, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthNotNull ) );
485  }
486  else
487  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintNotNull );
488  if ( constraints & QgsFieldConstraints::ConstraintUnique )
489  {
490  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintOrigin>( originUnique ) );
491  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintUnique, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthUnique ) );
492  }
493  else
494  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintUnique );
495  if ( constraints & QgsFieldConstraints::ConstraintExpression )
496  {
497  fieldConstraints.setConstraint( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintOrigin>( originExpression ) );
498  fieldConstraints.setConstraintStrength( QgsFieldConstraints::ConstraintExpression, static_cast< QgsFieldConstraints::ConstraintStrength>( strengthExpression ) );
499  }
500  else
501  fieldConstraints.removeConstraint( QgsFieldConstraints::ConstraintExpression );
502  fieldConstraints.setConstraintExpression( constraintExpression, constraintDescription );
503  field.setConstraints( fieldConstraints );
504  field.setSubType( static_cast< QVariant::Type >( subType ) );
505  return in;
506 }
bool isNumeric() const
Returns if this field is numeric.
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
QString comment() const
Returns the field comment.
bool isDateOrTime() const
Returns if this field is a date and/or time type.
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:58
int precision
Definition: qgsfield.h:55
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:59
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:165
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:57
QDataStream & operator>>(QDataStream &in, QgsField &field)
Reads a field from stream in into field. QGIS version compatibility is not guaranteed.
Definition: qgsfield.cpp:445
void setDefaultValueDefinition(const QgsDefaultValue &defaultValueDefinition)
Sets an expression to use when calculating the default value for the field.
Definition: qgsfield.cpp:180
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:281
void setName(const QString &name)
Set the field name.
Definition: qgsfield.cpp:141
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:410
int precision() const
Gets the precision of the field.
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
QString name() const
Returns the name of the field.
Field has an expression constraint set. See constraintExpression().
int length
Definition: qgsfield.h:54
void setLength(int len)
Set the field length.
Definition: qgsfield.cpp:161
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:105
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:87
void setTypeName(const QString &typeName)
Set the field type.
Definition: qgsfield.cpp:156
const QString & typeName
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
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.
bool operator!=(const QgsField &other) const
Definition: qgsfield.cpp:77
QString displayString(const QVariant &v) const
Formats string for display.
Definition: qgsfield.cpp:211
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:151
QgsFieldConstraints constraints
Definition: qgsfield.h:61
void setType(QVariant::Type type)
Set variant type.
Definition: qgsfield.cpp:146
bool operator==(const QgsField &other) const
Definition: qgsfield.cpp:72
void setAlias(const QString &alias)
Sets the alias for the field (the friendly displayed name of the field ).
Definition: qgsfield.cpp:200
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:100
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:185
void setComment(const QString &comment)
Set the field comment.
Definition: qgsfield.cpp:170
QVariant::Type type
Definition: qgsfield.h:56
QDataStream & operator<<(QDataStream &out, const QgsField &field)
Writes the field to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsfield.cpp:421
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:60
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:405