mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Apply default values on update
This commit is contained in:
parent
7b36287ff3
commit
f2d512a73a
@ -72,11 +72,17 @@ class QgsDefaultValue
|
||||
|
||||
bool isValid() const;
|
||||
%Docstring
|
||||
Returns if this default value is should be applied.
|
||||
Returns if this default value should be applied.
|
||||
:return: false if the expression is a null string.
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
operator bool() const;
|
||||
%Docstring
|
||||
Checks if a default value is set. Alias for isValid().
|
||||
:return: false if the expression is a null string.
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
|
@ -925,7 +925,7 @@ Return the provider type for this layer
|
||||
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
|
||||
|
||||
|
||||
bool updateFeature( QgsFeature &f );
|
||||
bool updateFeature( const QgsFeature &f );
|
||||
%Docstring
|
||||
Updates an existing feature. This method needs to query the datasource
|
||||
on every call. Consider using changeAttributeValue() or
|
||||
@ -1172,13 +1172,13 @@ Returns list of attributes making up the primary key
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geom );
|
||||
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue = false );
|
||||
%Docstring
|
||||
Change feature's geometry
|
||||
:rtype: bool
|
||||
%End
|
||||
|
||||
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant() );
|
||||
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false );
|
||||
%Docstring
|
||||
Changes an attribute value (but does not commit it)
|
||||
|
||||
|
@ -50,5 +50,10 @@ void QgsDefaultValue::setApplyOnUpdate( bool applyOnUpdate )
|
||||
|
||||
bool QgsDefaultValue::isValid() const
|
||||
{
|
||||
return mExpression.isEmpty();
|
||||
return !mExpression.isEmpty();
|
||||
}
|
||||
|
||||
QgsDefaultValue::operator bool() const
|
||||
{
|
||||
return !mExpression.isEmpty();
|
||||
}
|
||||
|
@ -84,11 +84,17 @@ class CORE_EXPORT QgsDefaultValue
|
||||
void setApplyOnUpdate( bool applyOnUpdate );
|
||||
|
||||
/**
|
||||
* Returns if this default value is should be applied.
|
||||
* Returns if this default value should be applied.
|
||||
* \returns false if the expression is a null string.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Checks if a default value is set. Alias for isValid().
|
||||
* \returns false if the expression is a null string.
|
||||
*/
|
||||
operator bool() const;
|
||||
|
||||
private:
|
||||
QString mExpression;
|
||||
bool mApplyOnUpdate = false;
|
||||
|
@ -766,6 +766,25 @@ void QgsVectorLayer::setExtent( const QgsRectangle &r )
|
||||
mValidExtent = true;
|
||||
}
|
||||
|
||||
void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
|
||||
{
|
||||
if ( !mDefaultValueOnUpdateFields.isEmpty() )
|
||||
{
|
||||
if ( !feature.isValid() )
|
||||
feature = getFeature( fid );
|
||||
|
||||
const QgsFields fields = mFields;
|
||||
int size = fields.size();
|
||||
for ( int idx : qgsAsConst( mDefaultValueOnUpdateFields ) )
|
||||
{
|
||||
if ( idx < 0 || idx >= size )
|
||||
continue;
|
||||
|
||||
defaultValue( idx, feature );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QgsRectangle QgsVectorLayer::extent() const
|
||||
{
|
||||
QgsRectangle rect;
|
||||
@ -941,47 +960,52 @@ bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
|
||||
return success;
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::updateFeature( QgsFeature &f )
|
||||
bool QgsVectorLayer::updateFeature( const QgsFeature &updatedFeature )
|
||||
{
|
||||
QgsFeatureRequest req;
|
||||
req.setFilterFid( f.id() );
|
||||
if ( !f.hasGeometry() )
|
||||
req.setFlags( QgsFeatureRequest::NoGeometry );
|
||||
if ( f.attributes().isEmpty() )
|
||||
req.setSubsetOfAttributes( QgsAttributeList() );
|
||||
bool hasChanged = false;
|
||||
bool hasError = false;
|
||||
|
||||
QgsFeature current;
|
||||
if ( !getFeatures( req ).nextFeature( current ) )
|
||||
QgsFeature currentFeature = getFeature( updatedFeature.id() );
|
||||
if ( currentFeature.isValid() )
|
||||
{
|
||||
QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( f.id() ) );
|
||||
return false;
|
||||
}
|
||||
QgsDebugMsg( QString( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ) );
|
||||
|
||||
if ( f.hasGeometry() && current.hasGeometry() && !f.geometry().isGeosEqual( current.geometry() ) )
|
||||
{
|
||||
if ( !changeGeometry( f.id(), f.geometry() ) )
|
||||
if ( updatedFeature.hasGeometry() && currentFeature.hasGeometry() && !updatedFeature.geometry().isGeosEqual( currentFeature.geometry() ) )
|
||||
{
|
||||
QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( f.id() ) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributes fa = f.attributes();
|
||||
QgsAttributes ca = current.attributes();
|
||||
|
||||
for ( int attr = 0; attr < fa.count(); ++attr )
|
||||
{
|
||||
if ( fa.at( attr ) != ca.at( attr ) )
|
||||
{
|
||||
if ( !changeAttributeValue( f.id(), attr, fa.at( attr ), ca.at( attr ) ) )
|
||||
if ( changeGeometry( updatedFeature.id(), updatedFeature.geometry(), true ) )
|
||||
{
|
||||
QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( f.id() ) );
|
||||
return false;
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributes fa = updatedFeature.attributes();
|
||||
QgsAttributes ca = currentFeature.attributes();
|
||||
|
||||
for ( int attr = 0; attr < fa.count(); ++attr )
|
||||
{
|
||||
if ( fa.at( attr ) != ca.at( attr ) )
|
||||
{
|
||||
if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
|
||||
{
|
||||
hasChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsDebugMsg( QString( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ) );
|
||||
hasError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() )
|
||||
updateDefaultValues( updatedFeature.id(), updatedFeature );
|
||||
|
||||
return !hasError;
|
||||
}
|
||||
|
||||
|
||||
@ -2260,7 +2284,7 @@ bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &error
|
||||
}
|
||||
|
||||
|
||||
bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, const QgsGeometry &geom )
|
||||
bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue )
|
||||
{
|
||||
if ( !mEditBuffer || !mDataProvider )
|
||||
{
|
||||
@ -2272,33 +2296,40 @@ bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, const QgsGeometry &geom )
|
||||
bool result = mEditBuffer->changeGeometry( fid, geom );
|
||||
|
||||
if ( result )
|
||||
{
|
||||
updateExtents();
|
||||
if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
|
||||
updateDefaultValues( fid );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue )
|
||||
bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch ( fields().fieldOrigin( field ) )
|
||||
{
|
||||
case QgsFields::OriginJoin:
|
||||
return mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
|
||||
result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
|
||||
|
||||
case QgsFields::OriginProvider:
|
||||
case QgsFields::OriginEdit:
|
||||
case QgsFields::OriginExpression:
|
||||
{
|
||||
if ( !mEditBuffer || !mDataProvider )
|
||||
return false;
|
||||
else
|
||||
return mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
|
||||
if ( mEditBuffer && mDataProvider )
|
||||
result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
|
||||
}
|
||||
|
||||
case QgsFields::OriginUnknown:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
|
||||
updateDefaultValues( fid );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::addAttribute( const QgsField &field )
|
||||
@ -2920,6 +2951,9 @@ void QgsVectorLayer::updateFields()
|
||||
|
||||
mFields[ index ].setAlias( aliasIt.value() );
|
||||
}
|
||||
|
||||
// Update default values
|
||||
mDefaultValueOnUpdateFields.clear();
|
||||
QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
|
||||
for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
|
||||
{
|
||||
@ -2928,6 +2962,8 @@ void QgsVectorLayer::updateFields()
|
||||
continue;
|
||||
|
||||
mFields[ index ].setDefaultValue( defaultIt.value() );
|
||||
if ( defaultIt.value().applyOnUpdate() )
|
||||
mDefaultValueOnUpdateFields.insert( index );
|
||||
}
|
||||
|
||||
QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
|
||||
|
@ -913,7 +913,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
\param f Feature to update
|
||||
\returns True in case of success and False in case of error
|
||||
*/
|
||||
bool updateFeature( QgsFeature &f );
|
||||
bool updateFeature( const QgsFeature &f );
|
||||
|
||||
/** Insert a new vertex before the given vertex number,
|
||||
* in the given ring, item (first number is index 0), and feature
|
||||
@ -1142,7 +1142,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
bool setReadOnly( bool readonly = true );
|
||||
|
||||
//! Change feature's geometry
|
||||
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geom );
|
||||
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue = false );
|
||||
|
||||
/**
|
||||
* Changes an attribute value (but does not commit it)
|
||||
@ -1154,7 +1154,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
*
|
||||
* \returns true in case of success
|
||||
*/
|
||||
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant() );
|
||||
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false );
|
||||
|
||||
/** Add an attribute field (but does not commit it)
|
||||
* returns true if the field was added
|
||||
@ -1958,6 +1958,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
|
||||
private: // Private methods
|
||||
|
||||
void updateDefaultValues( QgsFeatureId fid, QgsFeature feature = QgsFeature() );
|
||||
|
||||
/**
|
||||
* Returns true if the provider is in read-only mode
|
||||
*/
|
||||
@ -2014,6 +2016,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
//! Map which stores default value expressions for fields
|
||||
QMap<QString, QgsDefaultValue> mDefaultExpressionMap;
|
||||
|
||||
//! An internal structure to keep track of fields that have a defaultValueOnUpdate
|
||||
QSet<int> mDefaultValueOnUpdateFields;
|
||||
|
||||
//! Map which stores constraints for fields
|
||||
QMap< QString, QgsFieldConstraints::Constraints > mFieldConstraints;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user