diff --git a/app/attributes/attributecontroller.cpp b/app/attributes/attributecontroller.cpp index af1822374..e8697ef42 100644 --- a/app/attributes/attributecontroller.cpp +++ b/app/attributes/attributecontroller.cpp @@ -129,13 +129,37 @@ void AttributeController::prefillRelationReferenceField() { QVariant foreignKey = mParentController->featureLayerPair().feature().attribute( fieldPair.referencedField() ); QString referencingField = fieldPair.referencingField(); - const QgsVectorLayer *childLayer = mLinkedRelation.referencingLayer(); - if ( childLayer ) + + std::shared_ptr formItem; + for ( const auto &item : mFormItems ) + { + if ( item->field().name() == referencingField ) + { + formItem = item; + break; + } + } + + if ( formItem ) { - const int fieldIndex = childLayer->fields().lookupField( referencingField ); - if ( fieldIndex != -1 ) + //if the field is in the form, setFormValue updates both the feature attribute and UI + setFormValue( formItem->id(), foreignKey ); + } + else + { + // if the field is not displayed in the form, then set the attribute directly on the feature + const QgsVectorLayer *childLayer = mLinkedRelation.referencingLayer(); + if ( childLayer ) + { + const int fieldIndex = childLayer->fields().lookupField( referencingField ); + if ( fieldIndex != -1 ) + mFeatureLayerPair.featureRef().setAttribute( fieldIndex, foreignKey ); + else + CoreUtils::log( "Attribute Controller - Relations", QStringLiteral( "Could not find field index for field %1" ).arg( referencingField ) ); + } + else { - mFeatureLayerPair.featureRef().setAttribute( fieldIndex, foreignKey ); + CoreUtils::log( "Attribute Controller - Relations", QStringLiteral( "Invalid child layer for relation %1" ).arg( mLinkedRelation.name() ) ); } } } diff --git a/app/test/testattributecontroller.cpp b/app/test/testattributecontroller.cpp index 9843a9af3..2145bb058 100644 --- a/app/test/testattributecontroller.cpp +++ b/app/test/testattributecontroller.cpp @@ -1219,3 +1219,56 @@ void TestAttributeController::testPhotoSketchingSave() QCOMPARE( f.attribute( testCaseResult.fieldIdx ), testCaseResult.expectedNewFieldValue ); } } + +void TestAttributeController::testPrefillRelationReferenceField() +{ + QString projectDir = TestUtils::testDataDir() + "/planes"; + QVERIFY( QgsProject::instance()->read( projectDir + "/quickapp_project.qgs" ) ); + + QgsVectorLayer *airportsLayer = dynamic_cast( + QgsProject::instance()->mapLayersByName( QStringLiteral( "airports" ) ).at( 0 ) ); + QVERIFY( airportsLayer && airportsLayer->isValid() ); + + QgsVectorLayer *towersLayer = dynamic_cast( + QgsProject::instance()->mapLayersByName( QStringLiteral( "airport-towers" ) ).at( 0 ) ); + QVERIFY( towersLayer && towersLayer->isValid() ); + + QgsRelation relation = QgsProject::instance()->relationManager()->relation( + QStringLiteral( "airport_to_airport_fk_airports_3_fid" ) ); + QVERIFY( relation.isValid() ); + + // parent controller holds an existing airports feature + QgsFeature parentFeature = airportsLayer->getFeature( 1 ); + QVERIFY( parentFeature.isValid() ); + + AttributeController parentController; + parentController.setFeatureLayerPair( FeatureLayerPair( parentFeature, airportsLayer ) ); + + // child controller holds a new empty airport-towers feature + QgsFeature childFeature; + childFeature.setValid( true ); + childFeature.setFields( towersLayer->fields(), true ); + + AttributeController childController; + childController.setFeatureLayerPair( FeatureLayerPair( childFeature, towersLayer ) ); + childController.setLinkedRelation( relation ); + childController.setParentController( &parentController ); // triggers prefillRelationReferenceField + + // find the airport_fk FormItem in the child controller + const FormItem *fkItem = nullptr; + const TabItem *tab = childController.tabItem( 0 ); + QVERIFY( tab ); + for ( const QUuid &id : tab->formItems() ) + { + const FormItem *item = childController.formItem( id ); + if ( item && item->field().name() == QLatin1String( "airport_fk" ) ) + { + fkItem = item; + break; + } + } + + // compare that the rawValue is updated after setting the linked relation + QVERIFY( fkItem ); + QCOMPARE( fkItem->rawValue(), parentFeature.attribute( QStringLiteral( "fid" ) ) ); +} diff --git a/app/test/testattributecontroller.h b/app/test/testattributecontroller.h index 8090d00ff..5fa25b9dc 100644 --- a/app/test/testattributecontroller.h +++ b/app/test/testattributecontroller.h @@ -36,6 +36,12 @@ class TestAttributeController: public QObject * the sketches play nicely with renaming expressions and metadata gets copied too. */ void testPhotoSketchingSave(); + + /** + * Test that prefillRelationReferenceField sets the rawValue of the FK field in the child controller + * to the parent feature's referenced field value (FID). + */ + void testPrefillRelationReferenceField(); }; #endif // TESTATTRIBUTECONTROLLER_H