Skip to content

Commit

Permalink
Fix style constraint save when strength is NotSet
Browse files Browse the repository at this point in the history
Fix #58431

I feel that the underlying issue remains (which is that setting
the strength to NotSet removes it from the field but not
from the layer and that the default strength is Hard) but
since it was clearly made in purpose 8 years ago I am
not keen to change it lightly.
  • Loading branch information
elpaso committed Oct 7, 2024
1 parent fefba6c commit df947ef
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 4 deletions.
51 changes: 47 additions & 4 deletions src/core/vector/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3141,10 +3141,53 @@ bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString
{
QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );

// This manipulation is required because when the strength is set to NotSet the constraint is removed from
// the field but when the field is queried for the strength of a not-existing constraint it returns Hard by default,
// see issue #58431
QgsFieldConstraints::Constraints constraints { mFieldConstraints.value( field.name() ) };
QgsFieldConstraints::ConstraintStrength uniqueStrength { QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet };
QgsFieldConstraints::ConstraintStrength notNullStrength { QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet };
QgsFieldConstraints::ConstraintStrength expressionStrength { QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet };

QPair<QString, QgsFieldConstraints::Constraint> strengthKey { qMakePair( field.name(), QgsFieldConstraints::ConstraintUnique ) };

if ( mFieldConstraintStrength.contains( strengthKey ) && mFieldConstraintStrength.value( strengthKey ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet )
{
constraints.setFlag( QgsFieldConstraints::Constraint::ConstraintUnique, false );
}
else
{
uniqueStrength = mFieldConstraintStrength.value( strengthKey );
}

strengthKey = qMakePair( field.name(), QgsFieldConstraints::ConstraintNotNull );

if ( mFieldConstraintStrength.contains( strengthKey ) && mFieldConstraintStrength.value( strengthKey ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet )
{
constraints.setFlag( QgsFieldConstraints::Constraint::ConstraintNotNull, false );
}
else
{
notNullStrength = mFieldConstraintStrength.value( strengthKey );
}

strengthKey = qMakePair( field.name(), QgsFieldConstraints::ConstraintExpression );

if ( mFieldConstraintStrength.contains( strengthKey ) && mFieldConstraintStrength.value( strengthKey ) == QgsFieldConstraints::ConstraintStrength::ConstraintStrengthNotSet )
{
constraints.setFlag( QgsFieldConstraints::Constraint::ConstraintExpression, false );
}
else
{
expressionStrength = mFieldConstraintStrength.value( strengthKey );
}


constraintElem.setAttribute( QStringLiteral( "constraints" ), constraints );
constraintElem.setAttribute( QStringLiteral( "unique_strength" ), uniqueStrength );
constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), notNullStrength );
constraintElem.setAttribute( QStringLiteral( "exp_strength" ), expressionStrength );
constraintsElem.appendChild( constraintElem );
}
node.appendChild( constraintsElem );
Expand Down
29 changes: 29 additions & 0 deletions tests/src/python/test_qgsvectorlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4675,6 +4675,35 @@ def test_selection_properties(self):
self.assertEqual(vl2.selectionProperties().selectionColor(),
QColor(255, 0, 0))

def testConstraintsStrengthNotSet(self):
"""Test issue GH #58431 when strength NotSet becomes Hard"""

# Create a memory layer with unique constraints
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "test_unique", "memory")
self.assertTrue(layer.isValid())

# Se not constraint on fldtxt
layer.setFieldConstraint(0, QgsFieldConstraints.Constraint.ConstraintNotNull, QgsFieldConstraints.ConstraintStrength.ConstraintStrengthSoft)
layer.setFieldConstraint(0, QgsFieldConstraints.Constraint.ConstraintUnique, QgsFieldConstraints.ConstraintStrength.ConstraintStrengthNotSet)

# Export the style to QML
style = QgsMapLayerStyle()
temp_file = tempfile.mktemp(suffix='.qml')
layer.saveNamedStyle(temp_file)
layer.loadNamedStyle(temp_file)

# Check constraints at the field level
field = layer.fields().at(0)
constraints = field.constraints()
self.assertEqual(constraints.constraintStrength(QgsFieldConstraints.Constraint.ConstraintNotNull), QgsFieldConstraints.ConstraintStrength.ConstraintStrengthSoft)
self.assertEqual(constraints.constraintStrength(QgsFieldConstraints.Constraint.ConstraintUnique), QgsFieldConstraints.ConstraintStrength.ConstraintStrengthNotSet)

# Check constraints at the layer level
constraints = layer.fieldConstraintsAndStrength(0)
self.assertEqual(constraints[QgsFieldConstraints.Constraint.ConstraintNotNull], QgsFieldConstraints.ConstraintStrength.ConstraintStrengthSoft)
self.assertEqual(constraints[QgsFieldConstraints.Constraint.ConstraintUnique], QgsFieldConstraints.ConstraintStrength.ConstraintStrengthNotSet)


# TODO:
# - fetch rect: feat with changed geometry: 1. in rect, 2. out of rect
# - more join tests
Expand Down

0 comments on commit df947ef

Please sign in to comment.