Skip to content

Commit 9a2ca1c

Browse files
authored
Merge pull request #3673 from nyalldawson/constraints
[FEATURE] Improved constraint handling, pt 1
2 parents 100667a + 9b9a002 commit 9a2ca1c

File tree

65 files changed

+2416
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2416
-438
lines changed

doc/api_break.dox

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,10 +736,16 @@ QgsEditFormConfig {#qgis_api_break_3_0_QgsEditFormConfig}
736736
- widgetType() and widgetConfig() now reflect only the user configured values.
737737
QgsEditorWidgetRegistry::instance()->findBest() must be used instead.
738738
- widgetType(), widgetConfig(), setWidgetType(), setWidgetConfig() and removeWidgetConfig() now only take a string as first parameter. Access by index has been removed.
739-
- expression() has been renamed to constraintExpression()
740-
- setExpression() has been renamed to setConstraintExpression()
741-
- expressionDescription() has been renamed to constraintDescription()
742-
- setExpressionDesctiption() has been renamed to setConstraintDescription()
739+
- expression(), setExpression(), expressionDescription() and setExpressionDescription()
740+
have been removed. Use QgsVectorLayer.setConstraintExpression()/constraintExpression(),
741+
or QgsField.constraintExpression()/QgsField.constraintDescription() instead.
742+
- notNull() and setNotNull() have been removed. Use QgsVectorLayer.setFieldConstraint()/fieldConstraints(), or QgsField.constraints() instead.
743+
744+
QgsEditorWidgetWrapper {#qgis_api_break_3_0_QgsEditorWidgetWrapper}
745+
----------------------
746+
747+
- constraintStatusChanged now reports a QgsEditorWidgetWrapper::ConstraintResult instead of the previous boolean value for the constraint status
748+
- The boolean constraintValid argument for updateConstraintWidgetStatus has been changed to a QgsEditorWidgetWrapper::ConstraintResult value
743749

744750

745751
QgsExpression {#qgis_api_break_3_0_QgsExpression}

python/core/core.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
%Include qgsfeaturerequest.sip
5757
%Include qgsfeedback.sip
5858
%Include qgsfield.sip
59+
%Include qgsfieldconstraints.sip
5960
%Include qgsfields.sip
6061
%Include qgsgeometrysimplifier.sip
6162
%Include qgsgeometryvalidator.sip
@@ -148,6 +149,7 @@
148149
%Include qgsvectorlayerimport.sip
149150
%Include qgsvectorlayerjoinbuffer.sip
150151
%Include qgsvectorlayerundocommand.sip
152+
%Include qgsvectorlayerutils.sip
151153
%Include qgsvectorsimplifymethod.sip
152154

153155
%Include qgscachedfeatureiterator.sip

python/core/qgseditformconfig.sip

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -197,61 +197,6 @@ class QgsEditFormConfig
197197
*/
198198
void setReadOnly( int idx, bool readOnly = true );
199199

200-
/**
201-
* Returns the constraint expression of a specific field
202-
*
203-
* @param idx The index of the field
204-
* @return the expression
205-
*
206-
* @note added in QGIS 2.16
207-
* @note renamed in QGIS 3.0
208-
*/
209-
QString constraintExpression( int idx ) const;
210-
211-
/**
212-
* Set the constraint expression for a specific field
213-
*
214-
* @param idx the field index
215-
* @param expression the constraint expression
216-
*
217-
* @note added in QGIS 2.16
218-
* @note renamed in QGIS 3.0
219-
*/
220-
void setConstraintExpression( int idx, const QString& expression );
221-
222-
/**
223-
* Returns the constraint expression description of a specific field.
224-
*
225-
* @param idx The index of the field
226-
* @return The expression description. Will be presented
227-
* to the user in case the constraint fails.
228-
*
229-
* @note added in QGIS 2.16
230-
* @note renamed in QGIS 3.0
231-
*/
232-
QString constraintDescription( int idx ) const;
233-
234-
/**
235-
* Set the constraint expression description for a specific field.
236-
*
237-
* @param idx The index of the field
238-
* @param description The description of the expression. Will be presented
239-
* to the user in case the constraint fails.
240-
*
241-
* @note added in QGIS 2.16
242-
* @note renamed in QGIS 3.0
243-
*/
244-
void setContraintDescription( int idx, const QString& description );
245-
246-
/**
247-
* Returns if the field at fieldidx should be treated as NOT NULL value
248-
*/
249-
bool notNull( int fieldidx ) const;
250-
/**
251-
* Set if the field at fieldidx should be treated as NOT NULL value
252-
*/
253-
void setNotNull( int idx, bool notnull = true );
254-
255200
/**
256201
* If this returns true, the widget at the given index will receive its label on the previous line
257202
* while if it returns false, the widget will receive its label on the left hand side.

python/core/qgsfield.sip

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class QgsField
1414
%End
1515

1616
public:
17+
1718
/** Constructor. Constructs a new QgsField object.
1819
* @param name Field name
1920
* @param type Field variant type, currently supported: String / Int / Double
@@ -162,6 +163,20 @@ class QgsField
162163
*/
163164
void setDefaultValueExpression( const QString& expression );
164165

166+
/**
167+
* Returns constraints which are present for the field.
168+
* @note added in QGIS 3.0
169+
* @see setConstraints()
170+
*/
171+
const QgsFieldConstraints& constraints() const;
172+
173+
/**
174+
* Sets constraints which are present for the field.
175+
* @note added in QGIS 3.0
176+
* @see constraints()
177+
*/
178+
void setConstraints( const QgsFieldConstraints& constraints );
179+
165180
/** Returns the alias for the field (the friendly displayed name of the field ),
166181
* or an empty string if there is no alias.
167182
* @see setAlias()
@@ -254,3 +269,4 @@ class QgsField
254269
*/
255270
const QgsEditorWidgetSetup& editorWidgetSetup() const;
256271
}; // class QgsField
272+
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/**
2+
* \class QgsFieldConstraints
3+
* \ingroup core
4+
* Stores information about constraints which may be present on a field.
5+
* \note added in QGIS 3.0
6+
*/
7+
8+
9+
class QgsFieldConstraints
10+
{
11+
12+
%TypeHeaderCode
13+
#include <qgsfieldconstraints.h>
14+
%End
15+
16+
public:
17+
18+
/**
19+
* Constraints which may be present on a field.
20+
*/
21+
enum Constraint
22+
{
23+
ConstraintNotNull, //!< Field may not be null
24+
ConstraintUnique, //!< Field must have a unique value
25+
ConstraintExpression, //!< Field has an expression constraint set. See constraintExpression().
26+
};
27+
typedef QFlags<QgsFieldConstraints::Constraint> Constraints;
28+
29+
/**
30+
* Origin of constraints.
31+
*/
32+
enum ConstraintOrigin
33+
{
34+
ConstraintOriginNotSet, //!< Constraint is not set
35+
ConstraintOriginProvider, //!< Constraint was set at data provider
36+
ConstraintOriginLayer, //!< Constraint was set by layer
37+
};
38+
39+
/**
40+
* Strength of constraints.
41+
*/
42+
enum ConstraintStrength
43+
{
44+
ConstraintStrengthNotSet, //!< Constraint is not set
45+
ConstraintStrengthHard, //!< Constraint must be honored before feature can be accepted
46+
ConstraintStrengthSoft, //!< User is warned if constraint is violated but feature can still be accepted
47+
};
48+
49+
/**
50+
* Constructor for QgsFieldConstraints.
51+
*/
52+
QgsFieldConstraints();
53+
54+
/**
55+
* Returns any constraints which are present for the field.
56+
* @see setConstraints()
57+
* @see constraintOrigin()
58+
*/
59+
Constraints constraints() const;
60+
61+
/**
62+
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
63+
* is not present on this field.
64+
* @see constraints()
65+
*/
66+
ConstraintOrigin constraintOrigin( Constraint constraint ) const;
67+
68+
/**
69+
* Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint
70+
* is not present on this field.
71+
* @see constraints()
72+
* @see setConstraintStrength()
73+
*/
74+
ConstraintStrength constraintStrength( Constraint constraint ) const;
75+
76+
/**
77+
* Sets the strength of a constraint. Note that the strength of constraints which originate
78+
* from a provider cannot be changed. Constraints default to ConstraintStrengthHard unless
79+
* explicitly changed.
80+
* @see constraintStrength()
81+
*/
82+
void setConstraintStrength( Constraint constraint, ConstraintStrength strength );
83+
84+
/**
85+
* Sets a constraint on the field.
86+
* @see constraints()
87+
* @see removeConstraint()
88+
*/
89+
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );
90+
91+
/**
92+
* Removes a constraint from the field.
93+
* @see setConstraint()
94+
* @see constraints()
95+
*/
96+
void removeConstraint( Constraint constraint );
97+
98+
/**
99+
* Returns the constraint expression for the field, if set.
100+
* @see constraints()
101+
* @see constraintDescription()
102+
* @see setConstraintExpression()
103+
*/
104+
QString constraintExpression() const;
105+
106+
/**
107+
* Returns the descriptive name for the constraint expression.
108+
* @see constraints()
109+
* @see constraintExpression()
110+
* @see setConstraintExpression()
111+
*/
112+
QString constraintDescription() const;
113+
114+
/**
115+
* Set the constraint expression for the field. An optional descriptive name for the constraint
116+
* can also be set. Setting an empty expression will clear any existing expression constraint.
117+
* @see constraintExpression()
118+
* @see constraintDescription()
119+
* @see constraints()
120+
*/
121+
void setConstraintExpression( const QString& expression, const QString& description = QString() );
122+
123+
bool operator==( const QgsFieldConstraints& other ) const;
124+
125+
};
126+
127+
QFlags<QgsFieldConstraints::Constraint> operator|(QgsFieldConstraints::Constraint f1, QFlags<QgsFieldConstraints::Constraint> f2);

python/core/qgsvectordataprovider.sip

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ class QgsVectorDataProvider : QgsDataProvider
230230
*/
231231
virtual QVariant defaultValue( int fieldId ) const;
232232

233+
/**
234+
* Returns any constraints which are present at the provider for a specified
235+
* field index.
236+
* @note added in QGIS 3.0
237+
*/
238+
QgsFieldConstraints::Constraints fieldConstraints( int fieldIndex ) const;
239+
233240
/**
234241
* Changes geometries of existing features
235242
* @param geometry_map A QgsGeometryMap whose index contains the feature IDs

python/core/qgsvectorlayer.sip

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,62 @@ class QgsVectorLayer : QgsMapLayer
12571257
*/
12581258
QString defaultValueExpression( int index ) const;
12591259

1260+
/**
1261+
* Returns any constraints which are present for a specified
1262+
* field index. These constraints may be inherited from the layer's data provider
1263+
* or may be set manually on the vector layer from within QGIS.
1264+
* @note added in QGIS 3.0
1265+
* @see setFieldConstraint()
1266+
*/
1267+
QgsFieldConstraints::Constraints fieldConstraints( int fieldIndex ) const;
1268+
1269+
/**
1270+
* Sets a constraint for a specified field index. Any constraints inherited from the layer's
1271+
* data provider will be kept intact and cannot be modified. Ie, calling this method only allows for new
1272+
* constraints to be added on top of the existing provider constraints.
1273+
* @note added in QGIS 3.0
1274+
* @see fieldConstraints()
1275+
* @see removeFieldConstraint()
1276+
*/
1277+
void setFieldConstraint( int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength = QgsFieldConstraints::ConstraintStrengthHard );
1278+
1279+
/**
1280+
* Removes a constraint for a specified field index. Any constraints inherited from the layer's
1281+
* data provider will be kept intact and cannot be removed.
1282+
* @note added in QGIS 3.0
1283+
* @see fieldConstraints()
1284+
* @see setFieldConstraint()
1285+
*/
1286+
void removeFieldConstraint( int index, QgsFieldConstraints::Constraint constraint );
1287+
1288+
/**
1289+
* Returns the constraint expression for for a specified field index, if set.
1290+
* @note added in QGIS 3.0
1291+
* @see fieldConstraints()
1292+
* @see constraintDescription()
1293+
* @see setConstraintExpression()
1294+
*/
1295+
QString constraintExpression( int index ) const;
1296+
1297+
/**
1298+
* Returns the descriptive name for the constraint expression for a specified field index.
1299+
* @note added in QGIS 3.0
1300+
* @see constraints()
1301+
* @see constraintExpression()
1302+
* @see setConstraintExpression()
1303+
*/
1304+
QString constraintDescription( int index ) const;
1305+
1306+
/**
1307+
* Set the constraint expression for the specified field index. An optional descriptive name for the constraint
1308+
* can also be set. Setting an empty expression will clear any existing expression constraint.
1309+
* @note added in QGIS 3.0
1310+
* @see constraintExpression()
1311+
* @see constraintDescription()
1312+
* @see constraints()
1313+
*/
1314+
void setConstraintExpression( int index, const QString& expression, const QString& description = QString() );
1315+
12601316
/** Calculates a list of unique values contained within an attribute in the layer. Note that
12611317
* in some circumstances when unsaved changes are present for the layer then the returned list
12621318
* may contain outdated values (for instance when the attribute value in a saved feature has
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
/** \ingroup core
3+
* \class QgsVectorLayerUtils
4+
* \brief Contains utility methods for working with QgsVectorLayers.
5+
*
6+
* \note Added in version 3.0
7+
*/
8+
class QgsVectorLayerUtils
9+
{
10+
%TypeHeaderCode
11+
#include <qgsvectorlayerutils.h>
12+
%End
13+
public:
14+
15+
/**
16+
* Returns true if the specified value already exists within a field. This method can be used to test for uniqueness
17+
* of values inside a layer's attributes. An optional list of ignored feature IDs can be provided, if so, any features
18+
* with IDs within this list are ignored when testing for existance of the value.
19+
*/
20+
static bool valueExists( const QgsVectorLayer* layer, int fieldIndex, const QVariant& value, const QgsFeatureIds& ignoreIds = QgsFeatureIds() );
21+
22+
/**
23+
* Tests an attribute value to check whether it passes all constraints which are present on the corresponding field.
24+
* Returns true if the attribute value is valid for the field. Any constraint failures will be reported in the errors argument.
25+
* If the strength or origin parameter is set then only constraints with a matching strength/origin will be checked.
26+
*/
27+
static bool validateAttribute( const QgsVectorLayer* layer, const QgsFeature& feature, int attributeIndex, QStringList& errors /Out/,
28+
QgsFieldConstraints::ConstraintStrength strength = QgsFieldConstraints::ConstraintStrengthNotSet,
29+
QgsFieldConstraints::ConstraintOrigin origin = QgsFieldConstraints::ConstraintOriginNotSet );
30+
31+
};

0 commit comments

Comments
 (0)