QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsfieldvalidator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfieldvalidator.cpp - description
3  -------------------
4  begin : March 2011
5  copyright : (C) 2011 by SunilRajKiran-kCube
6  email : [email protected]
7 
8  adapted version of QValidator for QgsField
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 
20 #include "qgsfieldvalidator.h"
21 
22 #include <QValidator>
23 #include <QRegExpValidator>
24 #include <QDate>
25 #include <QVariant>
26 
27 #include "qgssettings.h"
28 #include "qgslogger.h"
29 #include "qgslonglongvalidator.h"
30 #include "qgsfields.h"
31 #include "qgsapplication.h"
32 
33 QgsFieldValidator::QgsFieldValidator( QObject *parent, const QgsField &field, const QString &defaultValue, const QString &dateFormat )
34  : QValidator( parent )
35  , mField( field )
36  , mDefaultValue( defaultValue )
37  , mDateFormat( dateFormat )
38 {
39  switch ( mField.type() )
40  {
41  case QVariant::Int:
42  {
43  if ( mField.length() > 0 )
44  {
45  QString re = QStringLiteral( "-?\\d{0,%1}" ).arg( mField.length() );
46  mValidator = new QRegExpValidator( QRegExp( re ), parent );
47  }
48  else
49  {
50  mValidator = new QIntValidator( parent );
51  }
52  }
53  break;
54 
55  case QVariant::Double:
56  {
57  if ( mField.length() > 0 && mField.precision() > 0 )
58  {
59  QString re;
60  // Also accept locale's decimalPoint if it's not a dot
61  if ( QLocale().decimalPoint() != '.' )
62  {
63  re = QStringLiteral( "-?\\d{0,%1}([\\.%2]\\d{0,%3})?" ).arg( mField.length() - mField.precision() ).arg( QLocale().decimalPoint() ).arg( mField.precision() );
64  }
65  else
66  {
67  re = QStringLiteral( "-?\\d{0,%1}([\\.,]\\d{0,%2})?" ).arg( mField.length() - mField.precision() ).arg( mField.precision() );
68  }
69  mValidator = new QRegExpValidator( QRegExp( re ), parent );
70  }
71  else if ( mField.length() > 0 && mField.precision() == 0 )
72  {
73  QString re = QStringLiteral( "-?\\d{0,%1}" ).arg( mField.length() );
74  mValidator = new QRegExpValidator( QRegExp( re ), parent );
75  }
76  else if ( mField.precision() > 0 )
77  {
78  QString re;
79  // Also accept locale's decimalPoint if it's not a dot
80  if ( QLocale().decimalPoint() != '.' )
81  {
82  re = QStringLiteral( "-?\\d*([\\.%1]\\d{0,%2})?" ).arg( QLocale().decimalPoint(), mField.precision() );
83  }
84  else
85  {
86  re = QStringLiteral( "-?\\d*([\\.]\\d{0,%1})?" ).arg( mField.precision() );
87  }
88  mValidator = new QRegExpValidator( QRegExp( re ), parent );
89  }
90  else
91  {
92  mValidator = new QDoubleValidator( parent );
93  }
94  }
95  break;
96 
97  case QVariant::LongLong :
98  mValidator = new QgsLongLongValidator( parent );
99  break;
100 
101  default:
102  mValidator = nullptr;
103  }
104 
105  mNullValue = QgsApplication::nullRepresentation();
106 }
107 
109 {
110  delete mValidator;
111 }
112 
113 QValidator::State QgsFieldValidator::validate( QString &s, int &i ) const
114 {
115  // empty values are considered NULL for numbers and dates and are acceptable
116  if ( s.isEmpty() &&
117  ( mField.type() == QVariant::Double
118  || mField.type() == QVariant::Int
119  || mField.type() == QVariant::LongLong
120  || mField.type() == QVariant::Date
121  )
122  )
123  {
124  return Acceptable;
125  }
126 
127  if ( s == mDefaultValue )
128  return Acceptable;
129 
130  // delegate to the child validator if any
131  if ( mValidator )
132  {
133  QValidator::State result = mValidator->validate( s, i );
134  return result;
135  }
136  else if ( mField.type() == QVariant::String )
137  {
138  if ( s == mNullValue )
139  return Acceptable;
140 
141  // allow entering the NULL representation, which might be longer than the actual field
142  if ( mField.length() > 0 && s.size() > mField.length() )
143  {
144  if ( !mNullValue.isEmpty() && !s.isEmpty() && s.size() < mNullValue.size() && s == mNullValue.left( s.size() ) )
145  return Intermediate;
146 
147  if ( !mDefaultValue.isEmpty() && !s.isEmpty() && s.size() < mDefaultValue.size() && s == mDefaultValue.left( s.size() ) )
148  return Intermediate;
149 
150  return Invalid;
151  }
152  }
153  else if ( mField.type() == QVariant::Date )
154  {
155  return QDate::fromString( s, mDateFormat ).isValid() ? Acceptable : Intermediate;
156  }
157  else
158  {
159  QgsDebugMsg( QStringLiteral( "unsupported type %1 for validation" ).arg( mField.type() ) );
160  return Invalid;
161  }
162 
163  return Acceptable;
164 }
165 
166 void QgsFieldValidator::fixup( QString &s ) const
167 {
168  if ( mValidator )
169  {
170  mValidator->fixup( s );
171  }
172  else if ( mField.type() == QVariant::String && mField.length() > 0 && s.size() > mField.length() && s != mDefaultValue )
173  {
174  // if the value is longer, this must be a partial NULL representation
175  s = mNullValue;
176  }
177  else if ( mField.type() == QVariant::Date )
178  {
179  // invalid dates will also translate to NULL
180  s = QString();
181  }
182 }
int precision
Definition: qgsfield.h:55
State validate(QString &s, int &i) const override
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsFieldValidator(QObject *parent, const QgsField &field, const QString &defaultValue, const QString &dateFormat="yyyy-MM-dd")
int length
Definition: qgsfield.h:54
static QString nullRepresentation()
This string is used to represent the value NULL throughout QGIS.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
void fixup(QString &s) const override
QVariant::Type type
Definition: qgsfield.h:56