Skip to content

Commit

Permalink
Move responsibility for storage of constraint expressions to QgsVecto…
Browse files Browse the repository at this point in the history
…rLayer
  • Loading branch information
nyalldawson committed Nov 2, 2016
1 parent f99ea26 commit 2500d75
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 181 deletions.
46 changes: 0 additions & 46 deletions python/core/qgseditformconfig.sip
Expand Up @@ -197,52 +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 );

/**
* 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.
Expand Down
1 change: 1 addition & 0 deletions python/core/qgsfield.sip
Expand Up @@ -23,6 +23,7 @@ class QgsField
{
ConstraintNotNull, //!< Field may not be null
ConstraintUnique, //!< Field must have a unique value
ConstraintExpression, //!< Field has an expression constraint set. See constraintExpression().
};
typedef QFlags<QgsField::Constraint> Constraints;

Expand Down
28 changes: 28 additions & 0 deletions python/core/qgsvectorlayer.sip
Expand Up @@ -1275,6 +1275,34 @@ class QgsVectorLayer : QgsMapLayer
*/
void setFieldConstraints( int index, QgsField::Constraints constraints );

/**
* 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
Expand Down
7 changes: 3 additions & 4 deletions src/app/qgsfieldsproperties.cpp
Expand Up @@ -977,8 +977,7 @@ void QgsFieldsProperties::apply()

editFormConfig.setReadOnly( i, !cfg.mEditable );
editFormConfig.setLabelOnTop( i, cfg.mLabelOnTop );
editFormConfig.setContraintDescription( i, cfg.mConstraintDescription );
editFormConfig.setConstraintExpression( i, cfg.mConstraint );
mLayer->setConstraintExpression( i, cfg.mConstraint, cfg.mConstraintDescription );

editFormConfig.setWidgetType( name, cfg.mEditorWidgetType );
editFormConfig.setWidgetConfig( name, cfg.mEditorWidgetConfig );
Expand Down Expand Up @@ -1062,8 +1061,8 @@ QgsFieldsProperties::FieldConfig::FieldConfig( QgsVectorLayer* layer, int idx )
&& layer->fields().fieldOrigin( idx ) != QgsFields::OriginExpression;
mLabelOnTop = layer->editFormConfig().labelOnTop( idx );
mConstraints = layer->fields().at( idx ).constraints();
mConstraint = layer->editFormConfig().constraintExpression( idx );
mConstraintDescription = layer->editFormConfig().constraintDescription( idx );
mConstraint = layer->fields().at( idx ).constraintExpression();
mConstraintDescription = layer->fields().at( idx ).constraintDescription();
const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( layer, layer->fields().field( idx ).name() );
mEditorWidgetType = setup.type();
mEditorWidgetConfig = setup.config();
Expand Down
38 changes: 0 additions & 38 deletions src/core/qgseditformconfig.cpp
Expand Up @@ -182,44 +182,6 @@ bool QgsEditFormConfig::labelOnTop( int idx ) const
return false;
}

QString QgsEditFormConfig::constraintExpression( int idx ) const
{
QString expr;

if ( idx >= 0 && idx < d->mFields.count() )
expr = d->mConstraints.value( d->mFields.at( idx ).name(), QString() );

return expr;
}

void QgsEditFormConfig::setConstraintExpression( int idx, const QString& expression )
{
if ( idx >= 0 && idx < d->mFields.count() )
{
d.detach();
d->mConstraints[ d->mFields.at( idx ).name()] = expression;
}
}

QString QgsEditFormConfig::constraintDescription( int idx ) const
{
QString description;

if ( idx >= 0 && idx < d->mFields.count() )
description = d->mConstraintsDescription[ d->mFields.at( idx ).name()];

return description;
}

void QgsEditFormConfig::setContraintDescription( int idx, const QString &descr )
{
if ( idx >= 0 && idx < d->mFields.count() )
{
d.detach();
d->mConstraintsDescription[ d->mFields.at( idx ).name()] = descr;
}
}

void QgsEditFormConfig::setReadOnly( int idx, bool readOnly )
{
if ( idx >= 0 && idx < d->mFields.count() )
Expand Down
46 changes: 0 additions & 46 deletions src/core/qgseditformconfig.h
Expand Up @@ -232,52 +232,6 @@ class CORE_EXPORT 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 );

/**
* 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.
Expand Down
4 changes: 0 additions & 4 deletions src/core/qgseditformconfig_p.h
Expand Up @@ -38,8 +38,6 @@ class QgsEditFormConfigPrivate : public QSharedData
: QSharedData( o )
, mInvisibleRootContainer( static_cast<QgsAttributeEditorContainer*>( o.mInvisibleRootContainer->clone( nullptr ) ) )
, mConfiguredRootContainer( o.mConfiguredRootContainer )
, mConstraints( o.mConstraints )
, mConstraintsDescription( o.mConstraintsDescription )
, mFieldEditables( o.mFieldEditables )
, mLabelOnTop( o.mLabelOnTop )
, mEditorWidgetTypes( o.mEditorWidgetTypes )
Expand All @@ -64,8 +62,6 @@ class QgsEditFormConfigPrivate : public QSharedData
//! This flag is set if the root container was configured by the user
bool mConfiguredRootContainer;

QMap< QString, QString> mConstraints;
QMap< QString, QString> mConstraintsDescription;
QMap< QString, bool> mFieldEditables;
QMap< QString, bool> mLabelOnTop;

Expand Down
77 changes: 77 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -1459,6 +1459,24 @@ bool QgsVectorLayer::readXml( const QDomNode& layer_node )
mFieldConstraints.insert( field, static_cast< QgsField::Constraints >( constraints ) );
}
}
mFieldConstraintExpressions.clear();
QDomNode constraintExpressionsNode = layer_node.namedItem( "constraintExpressions" );
if ( !constraintExpressionsNode.isNull() )
{
QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( "constraint" );
for ( int i = 0; i < constraintNodeList.size(); ++i )
{
QDomElement constraintElem = constraintNodeList.at( i ).toElement();

QString field = constraintElem.attribute( "field", QString() );
QString exp = constraintElem.attribute( "exp", QString() );
QString desc = constraintElem.attribute( "desc", QString() );
if ( field.isEmpty() || exp.isEmpty() )
continue;

mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
}
}

updateFields();

Expand Down Expand Up @@ -1677,6 +1695,19 @@ bool QgsVectorLayer::writeXml( QDomNode & layer_node,
}
layer_node.appendChild( constraintsElem );

// constraint expressions
QDomElement constraintExpressionsElem = document.createElement( "constraintExpressions" );
Q_FOREACH ( const QgsField& field, mFields )
{
QDomElement constraintExpressionElem = document.createElement( "constraint" );
constraintExpressionElem.setAttribute( "field", field.name() );
constraintExpressionElem.setAttribute( "exp", field.constraintExpression() );
constraintExpressionElem.setAttribute( "desc", field.constraintDescription() );
constraintExpressionsElem.appendChild( constraintExpressionElem );
}
layer_node.appendChild( constraintExpressionsElem );


// change dependencies
QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
Q_FOREACH ( const QgsMapLayerDependency& dep, dependencies() )
Expand Down Expand Up @@ -2948,6 +2979,20 @@ void QgsVectorLayer::updateFields()
mFields[ index ].setConstraint( QgsField::ConstraintExpression, QgsField::ConstraintOriginLayer );
}

QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
{
int index = mFields.lookupField( constraintExpIt.key() );
if ( index < 0 )
continue;

// always keep provider constraints intact
if ( mFields.at( index ).constraintOrigin( QgsField::ConstraintExpression ) == QgsField::ConstraintOriginProvider )
continue;

mFields[ index ].setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
}

if ( oldFields != mFields )
{
emit updatedFields();
Expand Down Expand Up @@ -4268,3 +4313,35 @@ void QgsVectorLayer::setFieldConstraints( int index, QgsField::Constraints const
}
updateFields();
}

QString QgsVectorLayer::constraintExpression( int index ) const
{
if ( index < 0 || index >= mFields.count() )
return QString();

return mFields.at( index ).constraintExpression();
}

QString QgsVectorLayer::constraintDescription( int index ) const
{
if ( index < 0 || index >= mFields.count() )
return QString();

return mFields.at( index ).constraintDescription();
}

void QgsVectorLayer::setConstraintExpression( int index, const QString& expression, const QString& description )
{
if ( index < 0 || index >= mFields.count() )
return;

if ( expression.isEmpty() )
{
mFieldConstraintExpressions.remove( mFields.at( index ).name() );
}
else
{
mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
}
updateFields();
}
31 changes: 31 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1415,6 +1415,34 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
void setFieldConstraints( int index, QgsField::Constraints constraints );

/**
* 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
Expand Down Expand Up @@ -1955,6 +1983,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
//! Map which stores constraints for fields
QMap< QString, QgsField::Constraints > mFieldConstraints;

//! Map which stores expression constraints for fields. Value is a pair of expression/description.
QMap< QString, QPair< QString, QString > > mFieldConstraintExpressions;

//! Holds the configuration for the edit form
QgsEditFormConfig mEditFormConfig;

Expand Down

0 comments on commit 2500d75

Please sign in to comment.