| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- #include "qfield_testbase.h"
- #include "qgsquickmapsettings.h"
- #include "referencingfeaturelistmodel.h"
- #include <QtTest>
- #include <qgsapplication.h>
- #include <qgsproject.h>
- #include <qgsrelationmanager.h>
- #include <qgsvectorlayer.h>
- class TestReferencingFeatureListModel : public QObject
- {
- Q_OBJECT
- private slots:
- void initTestCase()
- {
- /* TEST PROJECT
- *
- * LAYERS
- * land (id, name, king_id)
- * - 0 Mordor
- * - 1 Gondor
- * - 2 Rohan
- * - 3 Eriador
- * king
- * - 0 Frodo (Gondor, Rohan, Eriador)
- * - 1 Gollum (Mordor)
- * share (id, share, king_id, land_id)
- * - Mordor Frodo 20
- * - Gondor Frodo 40
- * - Rohan Frodo 60
- * - EriadorFrodo 100
- *
- * - Mordor Gollum 80
- * - Gondor Gollum 60
- * - Rohan Gollum 40
- *
- * RELATIONS
- * A king can rule several lands, but a land can be ruled by only one king
- * - landhasoneking (land m--1 king)
- * A king can have shares of several lands and a land can be owned by several kings
- * - sharehasoneoner (shares m--1 king)
- * - shareofoneland (shares m--1 land)
- */
- //create layers
- mL_Land.reset( new QgsVectorLayer( QStringLiteral( "Polygon?crs=EPSG:3857&field=id:int&field=name:string&field=king_id:int" ), QStringLiteral( "land" ), QStringLiteral( "memory" ) ) );
- mL_Land->setDisplayExpression( "name" );
- QVERIFY( mL_Land->isValid() );
- QgsProject::instance()->addMapLayer( mL_Land.get(), false, false );
- mL_King.reset( new QgsVectorLayer( QStringLiteral( "Point?crs=EPSG:3857&field=id:int&field=name:string" ), QStringLiteral( "king" ), QStringLiteral( "memory" ) ) );
- mL_King->setDisplayExpression( "name" );
- QVERIFY( mL_King->isValid() );
- QgsProject::instance()->addMapLayer( mL_King.get(), false, false );
- mL_Share.reset( new QgsVectorLayer( QStringLiteral( "Point?crs=EPSG:3857&field=id:integer&field=share:int&field=king_id:int&field=land_id:int" ), QStringLiteral( "share" ), QStringLiteral( "memory" ) ) );
- mL_Share->setDisplayExpression( "share" );
- QVERIFY( mL_Share->isValid() );
- QgsProject::instance()->addMapLayer( mL_Share.get(), false, false );
- //create relations
- mR_Landhasoneking.setId( QStringLiteral( "land.king" ) );
- mR_Landhasoneking.setName( QStringLiteral( "land.king" ) );
- mR_Landhasoneking.setReferencingLayer( mL_Land->id() );
- mR_Landhasoneking.setReferencedLayer( mL_King->id() );
- mR_Landhasoneking.addFieldPair( QStringLiteral( "king_id" ), QStringLiteral( "id" ) );
- QVERIFY( mR_Landhasoneking.isValid() );
- QgsProject::instance()->relationManager()->addRelation( mR_Landhasoneking );
- mR_Sharehasoneking.setId( QStringLiteral( "share.king" ) );
- mR_Sharehasoneking.setName( QStringLiteral( "share.king" ) );
- mR_Sharehasoneking.setReferencingLayer( mL_Share->id() );
- mR_Sharehasoneking.setReferencedLayer( mL_King->id() );
- mR_Sharehasoneking.addFieldPair( QStringLiteral( "king_id" ), QStringLiteral( "id" ) );
- QVERIFY( mR_Sharehasoneking.isValid() );
- QgsProject::instance()->relationManager()->addRelation( mR_Sharehasoneking );
- mR_Shareofoneland.setId( QStringLiteral( "share.land" ) );
- mR_Shareofoneland.setName( QStringLiteral( "share.land" ) );
- mR_Shareofoneland.setReferencingLayer( mL_Share->id() );
- mR_Shareofoneland.setReferencedLayer( mL_Land->id() );
- mR_Shareofoneland.addFieldPair( QStringLiteral( "land_id" ), QStringLiteral( "id" ) );
- QVERIFY( mR_Shareofoneland.isValid() );
- QgsProject::instance()->relationManager()->addRelation( mR_Shareofoneland );
- // add features on land
- QgsFeature land_ft0( mL_Land->fields() );
- land_ft0.setAttribute( QStringLiteral( "id" ), 0 );
- land_ft0.setAttribute( QStringLiteral( "name" ), "Mordor" );
- land_ft0.setAttribute( QStringLiteral( "king_id" ), 1 );
- QgsFeature land_ft1( mL_Land->fields() );
- land_ft1.setAttribute( QStringLiteral( "id" ), 1 );
- land_ft1.setAttribute( QStringLiteral( "name" ), "Gondor" );
- land_ft1.setAttribute( QStringLiteral( "king_id" ), 0 );
- QgsFeature land_ft2( mL_Land->fields() );
- land_ft2.setAttribute( QStringLiteral( "id" ), 2 );
- land_ft2.setAttribute( QStringLiteral( "name" ), "Rohan" );
- land_ft2.setAttribute( QStringLiteral( "king_id" ), 0 );
- QgsFeature land_ft3( mL_Land->fields() );
- land_ft3.setAttribute( QStringLiteral( "id" ), 3 );
- land_ft3.setAttribute( QStringLiteral( "name" ), "Eriador" );
- land_ft3.setAttribute( QStringLiteral( "king_id" ), 0 );
- mL_Land->startEditing();
- mL_Land->addFeature( land_ft0 );
- mL_Land->addFeature( land_ft1 );
- mL_Land->addFeature( land_ft2 );
- mL_Land->addFeature( land_ft3 );
- mL_Land->commitChanges();
- QCOMPARE( mL_Land->featureCount(), 4L );
- // add features on king
- QgsFeature king_ft0( mL_King->fields() );
- king_ft0.setAttribute( QStringLiteral( "id" ), 0 );
- king_ft0.setAttribute( QStringLiteral( "name" ), "Frodo" );
- QgsFeature king_ft1( mL_King->fields() );
- king_ft1.setAttribute( QStringLiteral( "id" ), 1 );
- king_ft1.setAttribute( QStringLiteral( "name" ), "Gollum" );
- mL_King->startEditing();
- mL_King->addFeature( king_ft0 );
- mL_King->addFeature( king_ft1 );
- mL_King->commitChanges();
- QCOMPARE( mL_King->featureCount(), 2L );
- // add features on share
- QgsFeature share_ft0( mL_Share->fields() );
- share_ft0.setAttribute( QStringLiteral( "id" ), 0 );
- share_ft0.setAttribute( QStringLiteral( "king_id" ), 0 );
- share_ft0.setAttribute( QStringLiteral( "land_id" ), 0 );
- share_ft0.setAttribute( QStringLiteral( "share" ), 20 );
- QgsFeature share_ft1( mL_Share->fields() );
- share_ft1.setAttribute( QStringLiteral( "id" ), 1 );
- share_ft1.setAttribute( QStringLiteral( "king_id" ), 0 );
- share_ft1.setAttribute( QStringLiteral( "land_id" ), 1 );
- share_ft1.setAttribute( QStringLiteral( "share" ), 40 );
- QgsFeature share_ft2( mL_Share->fields() );
- share_ft2.setAttribute( QStringLiteral( "id" ), 2 );
- share_ft2.setAttribute( QStringLiteral( "king_id" ), 0 );
- share_ft2.setAttribute( QStringLiteral( "land_id" ), 2 );
- share_ft2.setAttribute( QStringLiteral( "share" ), 60 );
- QgsFeature share_ft3( mL_Share->fields() );
- share_ft3.setAttribute( QStringLiteral( "id" ), 3 );
- share_ft3.setAttribute( QStringLiteral( "king_id" ), 0 );
- share_ft3.setAttribute( QStringLiteral( "land_id" ), 3 );
- share_ft3.setAttribute( QStringLiteral( "share" ), 100 );
- QgsFeature share_ft4( mL_Share->fields() );
- share_ft4.setAttribute( QStringLiteral( "id" ), 4 );
- share_ft4.setAttribute( QStringLiteral( "king_id" ), 1 );
- share_ft4.setAttribute( QStringLiteral( "land_id" ), 0 );
- share_ft4.setAttribute( QStringLiteral( "share" ), 80 );
- QgsFeature share_ft5( mL_Share->fields() );
- share_ft5.setAttribute( QStringLiteral( "id" ), 5 );
- share_ft5.setAttribute( QStringLiteral( "king_id" ), 1 );
- share_ft5.setAttribute( QStringLiteral( "land_id" ), 1 );
- share_ft5.setAttribute( QStringLiteral( "share" ), 60 );
- QgsFeature share_ft6( mL_Share->fields() );
- share_ft6.setAttribute( QStringLiteral( "id" ), 6 );
- share_ft6.setAttribute( QStringLiteral( "king_id" ), 1 );
- share_ft6.setAttribute( QStringLiteral( "land_id" ), 2 );
- share_ft6.setAttribute( QStringLiteral( "share" ), 40 );
- mL_Share->startEditing();
- mL_Share->addFeature( share_ft0 );
- mL_Share->addFeature( share_ft1 );
- mL_Share->addFeature( share_ft2 );
- mL_Share->addFeature( share_ft3 );
- mL_Share->addFeature( share_ft4 );
- mL_Share->addFeature( share_ft5 );
- mL_Share->addFeature( share_ft6 );
- mL_Share->commitChanges();
- QCOMPARE( mL_Share->featureCount(), 7L );
- mModel = new ReferencingFeatureListModel();
- }
- /*
- testGetReferencingFeatures
- - load project
- - create model (set relation, set feature)
- - count list / compare list
- - change parent feature
- - count list / compare list
- */
- void testGetReferencingFeatures()
- {
- mModel->setRelation( mR_Landhasoneking );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- mModel->setNmRelation( QgsRelation() );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- //check out Frodo
- mModel->setFeature( mL_King->getFeature( 1 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo rules 3 lands (Gondor, Rohan, Eriador)
- QCOMPARE( mModel->rowCount(), 3 );
- //check out Gollum
- mModel->setFeature( mL_King->getFeature( 2 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Gollum rules 1 land (Mordor)
- QCOMPARE( mModel->rowCount(), 1 );
- }
- /*
- testGetManyToManyReferencedFeatures
- - load project
- - create model (set relation, set nmrelation, set feature)
- - count list / compare list
- - change parent feature
- - count list / compare list
- */
- void testGetManyToManyReferencedFeatures()
- {
- mModel->setRelation( mR_Sharehasoneking );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- mModel->setNmRelation( mR_Shareofoneland );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- //check out Frodo
- mModel->setFeature( mL_King->getFeature( 1 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo has shares of 4 lands (Mordor, Gondor, Rohan, Eriador)
- QCOMPARE( mModel->rowCount(), 4 );
- //check out Gollum
- mModel->setFeature( mL_King->getFeature( 2 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Gollum has shares of 3 lands (Mordor, Gondor, Rohan)
- QCOMPARE( mModel->rowCount(), 3 );
- }
- /*
- testDeleteReferencingFeature
- - load project
- - create model (set relation, set feature)
- - count list / compare list
- - delete child features
- - count list / compare list
- */
- void testDeleteReferencingFeature()
- {
- mModel->setNmRelation( QgsRelation() );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- mModel->setRelation( mR_Landhasoneking );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- //check out Frodo
- mModel->setFeature( mL_King->getFeature( 1 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo rules 3 lands (Gondor, Rohan, Eriador)
- QCOMPARE( mModel->rowCount(), 3 );
- //check display string of rohan
- QString displayString = mModel->data( mModel->index( 1, 0 ), ReferencingFeatureListModel::DisplayString ).toString();
- QCOMPARE( displayString, QStringLiteral( "Gondor" ) );
- //delete Rohan
- mModel->deleteFeature( qvariant_cast<QgsFeature>( mModel->data( mModel->index( 1, 0 ), ReferencingFeatureListModel::ReferencingFeature ) ).id() );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo rules 2 lands (Gondor, Eriador) no Rohan anymore
- QCOMPARE( mModel->rowCount(), 2 );
- }
- /*
- testDdeleteReferenceToManyToManyReferencedFeature
- - load project
- - create model (set relation, set feature)
- - count list / compare list
- - delete (unlink) child features
- - count list / compare list
- */
- void testDeleteReferenceToManyToManyReferencedFeature()
- {
- mModel->setRelation( mR_Sharehasoneking );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- mModel->setNmRelation( mR_Shareofoneland );
- QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 500 );
- //check out Frodo
- mModel->setFeature( mL_King->getFeature( 1 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo has shares of 4 lands (Mordor, Gondor, Eriador, Rohan)
- QCOMPARE( mModel->rowCount(), 4 );
- //check out Gollum
- mModel->setFeature( mL_King->getFeature( 2 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Gollum has shares of 3 lands (Mordor, Gondor, Rohan)
- QCOMPARE( mModel->rowCount(), 3 );
- //check display string of Gollums Mordor share (80)
- QString displayString = mModel->data( mModel->index( 0, 0 ), ReferencingFeatureListModel::DisplayString ).toString();
- QCOMPARE( displayString, QStringLiteral( "40" ) );
- //delete Gollums share on Mordor
- mModel->deleteFeature( qvariant_cast<QgsFeature>( mModel->data( mModel->index( 0, 0 ), ReferencingFeatureListModel::ReferencingFeature ) ).id() );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Gollum has shares of 2 landd (Gondor, Rohan)
- QCOMPARE( mModel->rowCount(), 2 );
- //check out Frodo again
- mModel->setFeature( mL_King->getFeature( 1 ) );
- QVERIFY( QSignalSpy( mModel, &ReferencingFeatureListModel::modelUpdated ).wait( 1000 ) );
- //Frodo has still shares of 4 lands (Mordor, Gondor, Eriador, Rohan) because his shares are untouched
- QCOMPARE( mModel->rowCount(), 4 );
- }
- void cleanupTestCase()
- {
- delete mModel;
- QgsProject::instance()->removeMapLayer( mL_Land.get() );
- QgsProject::instance()->removeMapLayer( mL_King.get() );
- QgsProject::instance()->removeMapLayer( mL_Share.get() );
- }
- private:
- std::unique_ptr<QgsVectorLayer> mL_Land;
- std::unique_ptr<QgsVectorLayer> mL_King;
- std::unique_ptr<QgsVectorLayer> mL_Share;
- QgsRelation mR_Landhasoneking;
- QgsRelation mR_Sharehasoneking;
- QgsRelation mR_Shareofoneland;
- ReferencingFeatureListModel *mModel;
- };
- QFIELDTEST_MAIN( TestReferencingFeatureListModel )
- #include "test_referencingfeaturelistmodel.moc"
|