Skip to content
Permalink
Browse files

Merge pull request #3673 from nyalldawson/constraints

[FEATURE] Improved constraint handling, pt 1
  • Loading branch information
nyalldawson committed Nov 4, 2016
2 parents 100667a + 9b9a002 commit 9a2ca1cebdd040cf5a0d6501925baf53e882db66
Showing with 2,416 additions and 438 deletions.
  1. +10 −4 doc/api_break.dox
  2. +2 −0 python/core/core.sip
  3. +0 −55 python/core/qgseditformconfig.sip
  4. +16 −0 python/core/qgsfield.sip
  5. +127 −0 python/core/qgsfieldconstraints.sip
  6. +7 −0 python/core/qgsvectordataprovider.sip
  7. +56 −0 python/core/qgsvectorlayer.sip
  8. +31 −0 python/core/qgsvectorlayerutils.sip
  9. +37 −3 python/gui/editorwidgets/core/qgseditorwidgetwrapper.sip
  10. +2 −12 python/gui/editorwidgets/qgsrelationreferencewidgetwrapper.sip
  11. +77 −2 src/app/qgsattributetypedialog.cpp
  12. +46 −0 src/app/qgsattributetypedialog.h
  13. +60 −9 src/app/qgsfieldsproperties.cpp
  14. +2 −1 src/app/qgsfieldsproperties.h
  15. +4 −0 src/core/CMakeLists.txt
  16. +0 −55 src/core/qgseditformconfig.cpp
  17. +0 −55 src/core/qgseditformconfig.h
  18. +0 −6 src/core/qgseditformconfig_p.h
  19. +48 −3 src/core/qgsfield.cpp
  20. +17 −0 src/core/qgsfield.h
  21. +7 −1 src/core/qgsfield_p.h
  22. +101 −0 src/core/qgsfieldconstraints.cpp
  23. +165 −0 src/core/qgsfieldconstraints.h
  24. +9 −0 src/core/qgsvectordataprovider.cpp
  25. +7 −1 src/core/qgsvectordataprovider.h
  26. +210 −0 src/core/qgsvectorlayer.cpp
  27. +66 −0 src/core/qgsvectorlayer.h
  28. +121 −0 src/core/qgsvectorlayerutils.cpp
  29. +50 −0 src/core/qgsvectorlayerutils.h
  30. +11 −6 src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
  31. +76 −41 src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp
  32. +43 −5 src/gui/editorwidgets/core/qgseditorwidgetwrapper.h
  33. +1 −1 src/gui/editorwidgets/qgscolorwidgetwrapper.cpp
  34. +1 −1 src/gui/editorwidgets/qgscolorwidgetwrapper.h
  35. +15 −5 src/gui/editorwidgets/qgsexternalresourcewidgetwrapper.cpp
  36. +1 −1 src/gui/editorwidgets/qgsexternalresourcewidgetwrapper.h
  37. +13 −5 src/gui/editorwidgets/qgsfilenamewidgetwrapper.cpp
  38. +1 −1 src/gui/editorwidgets/qgsfilenamewidgetwrapper.h
  39. +1 −1 src/gui/editorwidgets/qgskeyvaluewidgetwrapper.cpp
  40. +1 −1 src/gui/editorwidgets/qgskeyvaluewidgetwrapper.h
  41. +2 −2 src/gui/editorwidgets/qgslistwidgetwrapper.cpp
  42. +1 −1 src/gui/editorwidgets/qgslistwidgetwrapper.h
  43. +13 −5 src/gui/editorwidgets/qgsphotowidgetwrapper.cpp
  44. +1 −1 src/gui/editorwidgets/qgsphotowidgetwrapper.h
  45. +15 −5 src/gui/editorwidgets/qgsrelationreferencewidgetwrapper.cpp
  46. +2 −12 src/gui/editorwidgets/qgsrelationreferencewidgetwrapper.h
  47. +13 −5 src/gui/editorwidgets/qgswebviewwidgetwrapper.cpp
  48. +1 −1 src/gui/editorwidgets/qgswebviewwidgetwrapper.h
  49. +34 −42 src/gui/qgsattributeform.cpp
  50. +3 −1 src/gui/qgsattributeform.h
  51. +1 −0 src/gui/qgsfilterlineedit.cpp
  52. +20 −9 src/providers/ogr/qgsogrprovider.cpp
  53. +21 −2 src/providers/postgres/qgspostgresprovider.cpp
  54. +61 −0 src/providers/spatialite/qgsspatialiteprovider.cpp
  55. +2 −0 src/providers/spatialite/qgsspatialiteprovider.h
  56. +81 −44 src/ui/qgsattributetypeedit.ui
  57. +90 −0 tests/src/core/testqgsfield.cpp
  58. +83 −31 tests/src/gui/testqgsattributeform.cpp
  59. +1 −0 tests/src/python/CMakeLists.txt
  60. +32 −1 tests/src/python/test_provider_ogr_sqlite.py
  61. +70 −0 tests/src/python/test_provider_postgres.py
  62. +59 −1 tests/src/python/test_provider_spatialite.py
  63. +164 −0 tests/src/python/test_qgsvectorlayer.py
  64. +183 −0 tests/src/python/test_qgsvectorlayerutils.py
  65. +21 −0 tests/testdata/provider/testdata_pg.sql
@@ -736,10 +736,16 @@ QgsEditFormConfig {#qgis_api_break_3_0_QgsEditFormConfig}
- widgetType() and widgetConfig() now reflect only the user configured values.
QgsEditorWidgetRegistry::instance()->findBest() must be used instead.
- widgetType(), widgetConfig(), setWidgetType(), setWidgetConfig() and removeWidgetConfig() now only take a string as first parameter. Access by index has been removed.
- expression() has been renamed to constraintExpression()
- setExpression() has been renamed to setConstraintExpression()
- expressionDescription() has been renamed to constraintDescription()
- setExpressionDesctiption() has been renamed to setConstraintDescription()
- expression(), setExpression(), expressionDescription() and setExpressionDescription()
have been removed. Use QgsVectorLayer.setConstraintExpression()/constraintExpression(),
or QgsField.constraintExpression()/QgsField.constraintDescription() instead.
- notNull() and setNotNull() have been removed. Use QgsVectorLayer.setFieldConstraint()/fieldConstraints(), or QgsField.constraints() instead.

QgsEditorWidgetWrapper {#qgis_api_break_3_0_QgsEditorWidgetWrapper}
----------------------

- constraintStatusChanged now reports a QgsEditorWidgetWrapper::ConstraintResult instead of the previous boolean value for the constraint status
- The boolean constraintValid argument for updateConstraintWidgetStatus has been changed to a QgsEditorWidgetWrapper::ConstraintResult value


QgsExpression {#qgis_api_break_3_0_QgsExpression}
@@ -56,6 +56,7 @@
%Include qgsfeaturerequest.sip
%Include qgsfeedback.sip
%Include qgsfield.sip
%Include qgsfieldconstraints.sip
%Include qgsfields.sip
%Include qgsgeometrysimplifier.sip
%Include qgsgeometryvalidator.sip
@@ -148,6 +149,7 @@
%Include qgsvectorlayerimport.sip
%Include qgsvectorlayerjoinbuffer.sip
%Include qgsvectorlayerundocommand.sip
%Include qgsvectorlayerutils.sip
%Include qgsvectorsimplifymethod.sip

%Include qgscachedfeatureiterator.sip
@@ -197,61 +197,6 @@ class QgsEditFormConfig
*/
void setReadOnly( int idx, bool readOnly = true );

/**
* Returns the constraint expression of a specific field
*
* @param idx The index of the field
* @return the expression
*
* @note added in QGIS 2.16
* @note renamed in QGIS 3.0
*/
QString constraintExpression( int idx ) const;

/**
* Set the constraint expression for a specific field
*
* @param idx the field index
* @param expression the constraint expression
*
* @note added in QGIS 2.16
* @note renamed in QGIS 3.0
*/
void setConstraintExpression( int idx, const QString& expression );

/**
* Returns the constraint expression description of a specific field.
*
* @param idx The index of the field
* @return The expression description. Will be presented
* to the user in case the constraint fails.
*
* @note added in QGIS 2.16
* @note renamed in QGIS 3.0
*/
QString constraintDescription( int idx ) const;

/**
* Set the constraint expression description for a specific field.
*
* @param idx The index of the field
* @param description The description of the expression. Will be presented
* to the user in case the constraint fails.
*
* @note added in QGIS 2.16
* @note renamed in QGIS 3.0
*/
void setContraintDescription( int idx, const QString& description );

/**
* Returns if the field at fieldidx should be treated as NOT NULL value
*/
bool notNull( int fieldidx ) const;
/**
* Set if the field at fieldidx should be treated as NOT NULL value
*/
void setNotNull( int idx, bool notnull = true );

/**
* If this returns true, the widget at the given index will receive its label on the previous line
* while if it returns false, the widget will receive its label on the left hand side.
@@ -14,6 +14,7 @@ class QgsField
%End

public:

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

/**
* Returns constraints which are present for the field.
* @note added in QGIS 3.0
* @see setConstraints()
*/
const QgsFieldConstraints& constraints() const;

/**
* Sets constraints which are present for the field.
* @note added in QGIS 3.0
* @see constraints()
*/
void setConstraints( const QgsFieldConstraints& constraints );

/** Returns the alias for the field (the friendly displayed name of the field ),
* or an empty string if there is no alias.
* @see setAlias()
@@ -254,3 +269,4 @@ class QgsField
*/
const QgsEditorWidgetSetup& editorWidgetSetup() const;
}; // class QgsField

@@ -0,0 +1,127 @@
/**
* \class QgsFieldConstraints
* \ingroup core
* Stores information about constraints which may be present on a field.
* \note added in QGIS 3.0
*/


class QgsFieldConstraints
{

%TypeHeaderCode
#include <qgsfieldconstraints.h>
%End

public:

/**
* Constraints which may be present on a field.
*/
enum Constraint
{
ConstraintNotNull, //!< Field may not be null
ConstraintUnique, //!< Field must have a unique value
ConstraintExpression, //!< Field has an expression constraint set. See constraintExpression().
};
typedef QFlags<QgsFieldConstraints::Constraint> Constraints;

/**
* Origin of constraints.
*/
enum ConstraintOrigin
{
ConstraintOriginNotSet, //!< Constraint is not set
ConstraintOriginProvider, //!< Constraint was set at data provider
ConstraintOriginLayer, //!< Constraint was set by layer
};

/**
* Strength of constraints.
*/
enum ConstraintStrength
{
ConstraintStrengthNotSet, //!< Constraint is not set
ConstraintStrengthHard, //!< Constraint must be honored before feature can be accepted
ConstraintStrengthSoft, //!< User is warned if constraint is violated but feature can still be accepted
};

/**
* Constructor for QgsFieldConstraints.
*/
QgsFieldConstraints();

/**
* Returns any constraints which are present for the field.
* @see setConstraints()
* @see constraintOrigin()
*/
Constraints constraints() const;

/**
* Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint
* is not present on this field.
* @see constraints()
*/
ConstraintOrigin constraintOrigin( Constraint constraint ) const;

/**
* Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint
* is not present on this field.
* @see constraints()
* @see setConstraintStrength()
*/
ConstraintStrength constraintStrength( Constraint constraint ) const;

/**
* Sets the strength of a constraint. Note that the strength of constraints which originate
* from a provider cannot be changed. Constraints default to ConstraintStrengthHard unless
* explicitly changed.
* @see constraintStrength()
*/
void setConstraintStrength( Constraint constraint, ConstraintStrength strength );

/**
* Sets a constraint on the field.
* @see constraints()
* @see removeConstraint()
*/
void setConstraint( Constraint constraint, ConstraintOrigin origin = ConstraintOriginLayer );

/**
* Removes a constraint from the field.
* @see setConstraint()
* @see constraints()
*/
void removeConstraint( Constraint constraint );

/**
* Returns the constraint expression for the field, if set.
* @see constraints()
* @see constraintDescription()
* @see setConstraintExpression()
*/
QString constraintExpression() const;

/**
* Returns the descriptive name for the constraint expression.
* @see constraints()
* @see constraintExpression()
* @see setConstraintExpression()
*/
QString constraintDescription() const;

/**
* Set the constraint expression for the field. An optional descriptive name for the constraint
* can also be set. Setting an empty expression will clear any existing expression constraint.
* @see constraintExpression()
* @see constraintDescription()
* @see constraints()
*/
void setConstraintExpression( const QString& expression, const QString& description = QString() );

bool operator==( const QgsFieldConstraints& other ) const;

};

QFlags<QgsFieldConstraints::Constraint> operator|(QgsFieldConstraints::Constraint f1, QFlags<QgsFieldConstraints::Constraint> f2);
@@ -230,6 +230,13 @@ class QgsVectorDataProvider : QgsDataProvider
*/
virtual QVariant defaultValue( int fieldId ) const;

/**
* Returns any constraints which are present at the provider for a specified
* field index.
* @note added in QGIS 3.0
*/
QgsFieldConstraints::Constraints fieldConstraints( int fieldIndex ) const;

/**
* Changes geometries of existing features
* @param geometry_map A QgsGeometryMap whose index contains the feature IDs
@@ -1257,6 +1257,62 @@ class QgsVectorLayer : QgsMapLayer
*/
QString defaultValueExpression( int index ) const;

/**
* Returns any constraints which are present for a specified
* field index. These constraints may be inherited from the layer's data provider
* or may be set manually on the vector layer from within QGIS.
* @note added in QGIS 3.0
* @see setFieldConstraint()
*/
QgsFieldConstraints::Constraints fieldConstraints( int fieldIndex ) const;

/**
* Sets a constraint for a specified field index. Any constraints inherited from the layer's
* data provider will be kept intact and cannot be modified. Ie, calling this method only allows for new
* constraints to be added on top of the existing provider constraints.
* @note added in QGIS 3.0
* @see fieldConstraints()
* @see removeFieldConstraint()
*/
void setFieldConstraint( int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength = QgsFieldConstraints::ConstraintStrengthHard );

/**
* Removes a constraint for a specified field index. Any constraints inherited from the layer's
* data provider will be kept intact and cannot be removed.
* @note added in QGIS 3.0
* @see fieldConstraints()
* @see setFieldConstraint()
*/
void removeFieldConstraint( int index, QgsFieldConstraints::Constraint constraint );

/**
* Returns the constraint expression for for a specified field index, if set.
* @note added in QGIS 3.0
* @see fieldConstraints()
* @see constraintDescription()
* @see setConstraintExpression()
*/
QString constraintExpression( int index ) const;

/**
* Returns the descriptive name for the constraint expression for a specified field index.
* @note added in QGIS 3.0
* @see constraints()
* @see constraintExpression()
* @see setConstraintExpression()
*/
QString constraintDescription( int index ) const;

/**
* Set the constraint expression for the specified field index. An optional descriptive name for the constraint
* can also be set. Setting an empty expression will clear any existing expression constraint.
* @note added in QGIS 3.0
* @see constraintExpression()
* @see constraintDescription()
* @see constraints()
*/
void setConstraintExpression( int index, const QString& expression, const QString& description = QString() );

/** Calculates a list of unique values contained within an attribute in the layer. Note that
* in some circumstances when unsaved changes are present for the layer then the returned list
* may contain outdated values (for instance when the attribute value in a saved feature has
@@ -0,0 +1,31 @@

/** \ingroup core
* \class QgsVectorLayerUtils
* \brief Contains utility methods for working with QgsVectorLayers.
*
* \note Added in version 3.0
*/
class QgsVectorLayerUtils
{
%TypeHeaderCode
#include <qgsvectorlayerutils.h>
%End
public:

/**
* Returns true if the specified value already exists within a field. This method can be used to test for uniqueness
* of values inside a layer's attributes. An optional list of ignored feature IDs can be provided, if so, any features
* with IDs within this list are ignored when testing for existance of the value.
*/
static bool valueExists( const QgsVectorLayer* layer, int fieldIndex, const QVariant& value, const QgsFeatureIds& ignoreIds = QgsFeatureIds() );

/**
* Tests an attribute value to check whether it passes all constraints which are present on the corresponding field.
* Returns true if the attribute value is valid for the field. Any constraint failures will be reported in the errors argument.
* If the strength or origin parameter is set then only constraints with a matching strength/origin will be checked.
*/
static bool validateAttribute( const QgsVectorLayer* layer, const QgsFeature& feature, int attributeIndex, QStringList& errors /Out/,
QgsFieldConstraints::ConstraintStrength strength = QgsFieldConstraints::ConstraintStrengthNotSet,
QgsFieldConstraints::ConstraintOrigin origin = QgsFieldConstraints::ConstraintOriginNotSet );

};

0 comments on commit 9a2ca1c

Please sign in to comment.
You can’t perform that action at this time.