Skip to content

Commit f99ea26

Browse files
committedNov 2, 2016
Refactor constraint handling
- store constraint origin in QgsField - move handling of constraint expressions to QgsField
1 parent 1cecf37 commit f99ea26

19 files changed

+302
-65
lines changed
 

‎python/core/qgsfield.sip

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ class QgsField
2626
};
2727
typedef QFlags<QgsField::Constraint> Constraints;
2828

29+
/**
30+
* Origin of constraints.
31+
* @note added in QGIS 3.0
32+
*/
33+
enum ConstraintOrigin
34+
{
35+
ConstraintOriginNotSet, //!< Constraint is not set
36+
ConstraintOriginProvider, //!< Constraint was set at data provider
37+
ConstraintOriginLayer, //!< Constraint was set by layer
38+
};
39+
2940
/** Constructor. Constructs a new QgsField object.
3041
* @param name Field name
3142
* @param type Field variant type, currently supported: String / Int / Double
@@ -178,15 +189,60 @@ class QgsField
178189
* Returns any constraints which are present for the field.
179190
* @note added in QGIS 3.0
180191
* @see setConstraints()
192+
* @see constraintOrigin()
181193
*/
182194
Constraints constraints() const;
183195

184196
/**
185-
* Sets constraints which are present for the field.
197+
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
198+
* is not present on this field.
199+
* @note added in QGIS 3.0
200+
* @see constraints()
201+
*/
202+
ConstraintOrigin constraintOrigin( Constraint constraint ) const;
203+
204+
/**
205+
* Sets a constraint on the field.
206+
* @note added in QGIS 3.0
207+
* @see constraints()
208+
* @see removeConstraint()
209+
*/
210+
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );
211+
212+
/**
213+
* Removes a constraint from the field.
214+
* @see setConstraint()
215+
* @see constraints()
216+
*/
217+
void removeConstraint( Constraint constraint );
218+
219+
/**
220+
* Returns the constraint expression for the field, if set.
221+
* @note added in QGIS 3.0
222+
* @see constraints()
223+
* @see constraintDescription()
224+
* @see setConstraintExpression()
225+
*/
226+
QString constraintExpression() const;
227+
228+
/**
229+
* Returns the descriptive name for the constraint expression.
230+
* @note added in QGIS 3.0
231+
* @see constraints()
232+
* @see constraintExpression()
233+
* @see setConstraintExpression()
234+
*/
235+
QString constraintDescription() const;
236+
237+
/**
238+
* Set the constraint expression for the field. An optional descriptive name for the constraint
239+
* can also be set. Setting an empty expression will clear any existing expression constraint.
186240
* @note added in QGIS 3.0
241+
* @see constraintExpression()
242+
* @see constraintDescription()
187243
* @see constraints()
188244
*/
189-
void setConstraints( Constraints constraints );
245+
void setConstraintExpression( const QString& expression, const QString& description = QString() );
190246

191247
/** Returns the alias for the field (the friendly displayed name of the field ),
192248
* or an empty string if there is no alias.

‎python/core/qgsvectordataprovider.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ class QgsVectorDataProvider : QgsDataProvider
235235
* field index.
236236
* @note added in QGIS 3.0
237237
*/
238-
virtual QgsField::Constraints fieldConstraints( int fieldIndex ) const;
238+
QgsField::Constraints fieldConstraints( int fieldIndex ) const;
239239

240240
/**
241241
* Changes geometries of existing features

‎src/app/qgsfieldsproperties.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,12 @@ void QgsFieldsProperties::attributeTypeDialog()
562562
attributeTypeDialog.setUnique( cfg.mConstraints & QgsField::ConstraintUnique );
563563

564564
QgsField::Constraints providerConstraints = 0;
565-
if ( mLayer->fields().fieldOrigin( index ) == QgsFields::OriginProvider )
566-
{
567-
providerConstraints = mLayer->dataProvider()->fieldConstraints( mLayer->fields().fieldOriginIndex( index ) );
568-
}
565+
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintNotNull ) == QgsField::ConstraintOriginProvider )
566+
providerConstraints |= QgsField::ConstraintNotNull;
567+
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintUnique ) == QgsField::ConstraintOriginProvider )
568+
providerConstraints |= QgsField::ConstraintUnique;
569+
if ( mLayer->fields().at( index ).constraintOrigin( QgsField::ConstraintExpression ) == QgsField::ConstraintOriginProvider )
570+
providerConstraints |= QgsField::ConstraintExpression;
569571
attributeTypeDialog.setProviderConstraints( providerConstraints );
570572

571573
attributeTypeDialog.setConstraintExpression( cfg.mConstraint );
@@ -1059,7 +1061,7 @@ QgsFieldsProperties::FieldConfig::FieldConfig( QgsVectorLayer* layer, int idx )
10591061
mEditableEnabled = layer->fields().fieldOrigin( idx ) != QgsFields::OriginJoin
10601062
&& layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression;
10611063
mLabelOnTop = layer->editFormConfig().labelOnTop( idx );
1062-
mConstraints = layer->fieldConstraints( idx );
1064+
mConstraints = layer->fields().at( idx ).constraints();
10631065
mConstraint = layer->editFormConfig().constraintExpression( idx );
10641066
mConstraintDescription = layer->editFormConfig().constraintDescription( idx );
10651067
const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( layer, layer->fields().field( idx ).name() );

‎src/core/qgsfield.cpp

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,55 @@ QgsField::Constraints QgsField::constraints() const
185185
return d->constraints;
186186
}
187187

188-
void QgsField::setConstraints( Constraints constraints )
188+
QgsField::ConstraintOrigin QgsField::constraintOrigin( QgsField::Constraint constraint ) const
189189
{
190-
d->constraints = constraints;
190+
if ( !( d->constraints & constraint ) )
191+
return ConstraintOriginNotSet;
192+
193+
return d->constraintOrigins.value( constraint, ConstraintOriginNotSet );
194+
}
195+
196+
void QgsField::setConstraint( QgsField::Constraint constraint, QgsField::ConstraintOrigin origin )
197+
{
198+
if ( origin == ConstraintOriginNotSet )
199+
{
200+
d->constraints &= ~constraint;
201+
d->constraintOrigins.remove( constraint );
202+
}
203+
else
204+
{
205+
d->constraints |= constraint;
206+
d->constraintOrigins.insert( constraint, origin );
207+
}
208+
}
209+
210+
void QgsField::removeConstraint( QgsField::Constraint constraint )
211+
{
212+
d->constraints &= ~constraint;
213+
}
214+
215+
QString QgsField::constraintExpression() const
216+
{
217+
return d->constraints & QgsField::ConstraintExpression ? d->expressionConstraint : QString();
218+
}
219+
220+
QString QgsField::constraintDescription() const
221+
{
222+
return d->expressionConstraintDescription;
223+
}
224+
225+
void QgsField::setConstraintExpression( const QString& expression, const QString& description )
226+
{
227+
if ( expression.isEmpty() )
228+
d->constraints &= ~QgsField::ConstraintExpression;
229+
else
230+
{
231+
d->constraints |= QgsField::ConstraintExpression;
232+
d->constraintOrigins.insert( QgsField::ConstraintExpression, QgsField::ConstraintOriginLayer );
233+
}
234+
235+
d->expressionConstraint = expression;
236+
d->expressionConstraintDescription = description;
191237
}
192238

193239
QString QgsField::alias() const
@@ -314,15 +360,22 @@ QDataStream& operator<<( QDataStream& out, const QgsField& field )
314360
out << field.alias();
315361
out << field.defaultValueExpression();
316362
out << field.constraints();
363+
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintNotNull ) );
364+
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintUnique ) );
365+
out << static_cast< quint32 >( field.constraintOrigin( QgsField::ConstraintExpression ) );
366+
out << field.constraintExpression();
367+
out << field.constraintDescription();
317368
out << static_cast< quint32 >( field.subType() );
318369
return out;
319370
}
320371

321372
QDataStream& operator>>( QDataStream& in, QgsField& field )
322373
{
323-
quint32 type, subType, length, precision, constraints;
324-
QString name, typeName, comment, alias, defaultValueExpression;
325-
in >> name >> type >> typeName >> length >> precision >> comment >> alias >> defaultValueExpression >> constraints >> subType;
374+
quint32 type, subType, length, precision, constraints, originNotNull, originUnique, originExpression;
375+
QString name, typeName, comment, alias, defaultValueExpression, constraintExpression, constraintDescription;
376+
in >> name >> type >> typeName >> length >> precision >> comment >> alias
377+
>> defaultValueExpression >> constraints >> originNotNull >> originUnique >> originExpression >>
378+
constraintExpression >> constraintDescription >> subType;
326379
field.setName( name );
327380
field.setType( static_cast< QVariant::Type >( type ) );
328381
field.setTypeName( typeName );
@@ -331,7 +384,19 @@ QDataStream& operator>>( QDataStream& in, QgsField& field )
331384
field.setComment( comment );
332385
field.setAlias( alias );
333386
field.setDefaultValueExpression( defaultValueExpression );
334-
field.setConstraints( static_cast< QgsField::Constraints>( constraints ) );
387+
if ( constraints & QgsField::ConstraintNotNull )
388+
field.setConstraint( QgsField::ConstraintNotNull, static_cast< QgsField::ConstraintOrigin>( originNotNull ) );
389+
else
390+
field.removeConstraint( QgsField::ConstraintNotNull );
391+
if ( constraints & QgsField::ConstraintUnique )
392+
field.setConstraint( QgsField::ConstraintUnique, static_cast< QgsField::ConstraintOrigin>( originUnique ) );
393+
else
394+
field.removeConstraint( QgsField::ConstraintUnique );
395+
if ( constraints & QgsField::ConstraintExpression )
396+
field.setConstraint( QgsField::ConstraintExpression, static_cast< QgsField::ConstraintOrigin>( originExpression ) );
397+
else
398+
field.removeConstraint( QgsField::ConstraintExpression );
399+
field.setConstraintExpression( constraintExpression, constraintDescription );
335400
field.setSubType( static_cast< QVariant::Type >( subType ) );
336401
return in;
337402
}

‎src/core/qgsfield.h

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class CORE_EXPORT QgsField
5454
Q_PROPERTY( QString name READ name WRITE setName )
5555
Q_PROPERTY( QString alias READ alias WRITE setAlias )
5656
Q_PROPERTY( QString defaultValueExpression READ defaultValueExpression WRITE setDefaultValueExpression )
57-
Q_PROPERTY( Constraints constraints READ constraints WRITE setConstraints )
57+
Q_PROPERTY( Constraints constraints READ constraints )
5858

5959
public:
6060

@@ -66,9 +66,21 @@ class CORE_EXPORT QgsField
6666
{
6767
ConstraintNotNull = 1, //!< Field may not be null
6868
ConstraintUnique = 1 << 1, //!< Field must have a unique value
69+
ConstraintExpression = 1 << 2, //!< Field has an expression constraint set. See constraintExpression().
6970
};
7071
Q_DECLARE_FLAGS( Constraints, Constraint )
7172

73+
/**
74+
* Origin of constraints.
75+
* @note added in QGIS 3.0
76+
*/
77+
enum ConstraintOrigin
78+
{
79+
ConstraintOriginNotSet = 0, //!< Constraint is not set
80+
ConstraintOriginProvider, //!< Constraint was set at data provider
81+
ConstraintOriginLayer, //!< Constraint was set by layer
82+
};
83+
7284
/** Constructor. Constructs a new QgsField object.
7385
* @param name Field name
7486
* @param type Field variant type, currently supported: String / Int / Double
@@ -225,15 +237,60 @@ class CORE_EXPORT QgsField
225237
* Returns any constraints which are present for the field.
226238
* @note added in QGIS 3.0
227239
* @see setConstraints()
240+
* @see constraintOrigin()
228241
*/
229242
Constraints constraints() const;
230243

231244
/**
232-
* Sets constraints which are present for the field.
245+
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
246+
* is not present on this field.
247+
* @note added in QGIS 3.0
248+
* @see constraints()
249+
*/
250+
ConstraintOrigin constraintOrigin( Constraint constraint ) const;
251+
252+
/**
253+
* Sets a constraint on the field.
254+
* @note added in QGIS 3.0
255+
* @see constraints()
256+
* @see removeConstraint()
257+
*/
258+
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );
259+
260+
/**
261+
* Removes a constraint from the field.
262+
* @see setConstraint()
263+
* @see constraints()
264+
*/
265+
void removeConstraint( Constraint constraint );
266+
267+
/**
268+
* Returns the constraint expression for the field, if set.
269+
* @note added in QGIS 3.0
270+
* @see constraints()
271+
* @see constraintDescription()
272+
* @see setConstraintExpression()
273+
*/
274+
QString constraintExpression() const;
275+
276+
/**
277+
* Returns the descriptive name for the constraint expression.
278+
* @note added in QGIS 3.0
279+
* @see constraints()
280+
* @see constraintExpression()
281+
* @see setConstraintExpression()
282+
*/
283+
QString constraintDescription() const;
284+
285+
/**
286+
* Set the constraint expression for the field. An optional descriptive name for the constraint
287+
* can also be set. Setting an empty expression will clear any existing expression constraint.
233288
* @note added in QGIS 3.0
289+
* @see constraintExpression()
290+
* @see constraintDescription()
234291
* @see constraints()
235292
*/
236-
void setConstraints( Constraints constraints );
293+
void setConstraintExpression( const QString& expression, const QString& description = QString() );
237294

238295
/** Returns the alias for the field (the friendly displayed name of the field ),
239296
* or an empty string if there is no alias.

‎src/core/qgsfield_p.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ class QgsFieldPrivate : public QSharedData
7171
, alias( other.alias )
7272
, defaultValueExpression( other.defaultValueExpression )
7373
, constraints( other.constraints )
74+
, constraintOrigins( other.constraintOrigins )
75+
, expressionConstraint( other.expressionConstraint )
76+
, expressionConstraintDescription( other.expressionConstraintDescription )
7477
{
7578
}
7679

@@ -81,7 +84,10 @@ class QgsFieldPrivate : public QSharedData
8184
return (( name == other.name ) && ( type == other.type ) && ( subType == other.subType )
8285
&& ( length == other.length ) && ( precision == other.precision )
8386
&& ( alias == other.alias ) && ( defaultValueExpression == other.defaultValueExpression )
84-
&& ( constraints == other.constraints ) );
87+
&& ( constraints == other.constraints )
88+
&& ( expressionConstraint == other.expressionConstraint )
89+
&& ( expressionConstraintDescription == other.expressionConstraintDescription )
90+
&& ( constraintOrigins == other.constraintOrigins ) );
8591
}
8692

8793
//! Name
@@ -114,6 +120,15 @@ class QgsFieldPrivate : public QSharedData
114120
//! Constraints
115121
QgsField::Constraints constraints;
116122

123+
//! Origin of field constraints
124+
QHash< QgsField::Constraint, QgsField::ConstraintOrigin > constraintOrigins;
125+
126+
//! Expression constraint
127+
QString expressionConstraint;
128+
129+
//! Expression constraint descriptive name
130+
QString expressionConstraintDescription;
131+
117132
QgsEditorWidgetSetup editorWidgetSetup;
118133
};
119134

‎src/core/qgsvectordataprovider.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,11 @@ QVariant QgsVectorDataProvider::defaultValue( int fieldId ) const
100100

101101
QgsField::Constraints QgsVectorDataProvider::fieldConstraints( int fieldIndex ) const
102102
{
103-
Q_UNUSED( fieldIndex );
104-
return 0;
103+
QgsFields f = fields();
104+
if ( fieldIndex < 0 || fieldIndex >= f.count() )
105+
return 0;
106+
107+
return f.at( fieldIndex ).constraints();
105108
}
106109

107110
bool QgsVectorDataProvider::changeGeometryValues( const QgsGeometryMap &geometry_map )

‎src/core/qgsvectordataprovider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
286286
* field index.
287287
* @note added in QGIS 3.0
288288
*/
289-
virtual QgsField::Constraints fieldConstraints( int fieldIndex ) const;
289+
QgsField::Constraints fieldConstraints( int fieldIndex ) const;
290290

291291
/**
292292
* Changes geometries of existing features

‎src/core/qgsvectorlayer.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2940,7 +2940,12 @@ void QgsVectorLayer::updateFields()
29402940
continue;
29412941

29422942
// always keep provider constraints intact
2943-
mFields[ index ].setConstraints( mFields.at( index ).constraints() | constraintIt.value() );
2943+
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintNotNull ) && ( constraintIt.value() & QgsField::ConstraintNotNull ) )
2944+
mFields[ index ].setConstraint( QgsField::ConstraintNotNull, QgsField::ConstraintOriginLayer );
2945+
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintUnique ) && ( constraintIt.value() & QgsField::ConstraintUnique ) )
2946+
mFields[ index ].setConstraint( QgsField::ConstraintUnique, QgsField::ConstraintOriginLayer );
2947+
if ( !( mFields.at( index ).constraints() & QgsField::ConstraintExpression ) && ( constraintIt.value() & QgsField::ConstraintExpression ) )
2948+
mFields[ index ].setConstraint( QgsField::ConstraintExpression, QgsField::ConstraintOriginLayer );
29442949
}
29452950

29462951
if ( oldFields != mFields )

0 commit comments

Comments
 (0)
Please sign in to comment.