[FEATURE] Duplicate features including children (one level deep) when relation strength is competition - configuration for the relationsstrength in the relation GUI [needs-docs]

This commit is contained in:
David 2017-10-25 17:04:48 +02:00
parent 6297d19b70
commit f7073d0587
14 changed files with 506 additions and 43 deletions

View File

@ -19,6 +19,13 @@ class QgsRelation
%End
public:
enum RelationStrength
{
Association,
Composition
};
QgsRelation();
%Docstring
@ -53,6 +60,12 @@ class QgsRelation
Set a name for this relation
%End
void setStrength( const RelationStrength &strength );
%Docstring
Set a strength for this relation
.. versionadded:: 3.0
%End
void setReferencingLayer( const QString &id );
%Docstring
Set the referencing (child) layer id. This layer will be searched in the registry.
@ -158,6 +171,15 @@ class QgsRelation
:rtype: str
%End
RelationStrength strength() const;
%Docstring
Returns the relation strength as a string
:return: strength
.. versionadded:: 3.0
:rtype: RelationStrength
%End
QString id() const;
%Docstring
A (project-wide) unique id for this relation

View File

@ -22,6 +22,38 @@ class QgsVectorLayerUtils
%End
public:
class QgsDuplicateFeatureContext
{
%Docstring
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features
.. versionadded:: 3.0
%End
%TypeHeaderCode
#include "qgsvectorlayerutils.h"
%End
public:
QgsDuplicateFeatureContext();
QList<QgsVectorLayer *> layers() const;
%Docstring
Returns all the layers in the member QMap mDuplicatedFeatures
.. versionadded:: 3.0
:rtype: list of QgsVectorLayer
%End
QgsFeatureIds duplicatedFeatures( QgsVectorLayer *layer ) const;
%Docstring
Returns the duplicated features in the given layer
.. versionadded:: 3.0
:rtype: QgsFeatureIds
%End
};
static bool valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds = QgsFeatureIds() );
%Docstring
Returns true if the specified value already exists within a field. This method can be used to test for uniqueness
@ -62,8 +94,18 @@ class QgsVectorLayerUtils
:rtype: QgsFeature
%End
static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext /Out/ );
%Docstring
Duplicates a feature and it's children (one level deep). It calls CreateFeature, so
default values and constraints (e.g., unique constraints) will automatically be handled.
The duplicated feature will be automatically inserted into the layer.
.. versionadded:: 3.0
:rtype: QgsFeature
%End
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -43,6 +43,17 @@ void QgsDiscoverRelationsDlg::addRelation( const QgsRelation &rel )
mRelationsTable->setItem( row, 2, new QTableWidgetItem( rel.fieldPairs().at( 0 ).referencingField() ) );
mRelationsTable->setItem( row, 3, new QTableWidgetItem( rel.referencedLayer()->name() ) );
mRelationsTable->setItem( row, 4, new QTableWidgetItem( rel.fieldPairs().at( 0 ).referencedField() ) );
if ( rel.strength() == QgsRelation::RelationStrength::Composition )
{
mRelationsTable->setItem( row, 5, new QTableWidgetItem( QStringLiteral( "Composition" ) ) );
}
else
{
mRelationsTable->setItem( row, 5, new QTableWidgetItem( QStringLiteral( "Association" ) ) );
}
mRelationsTable->item( row, 5 )->setToolTip( QStringLiteral( "Composition (child features will be copied too) or Association" ) );
}
QList<QgsRelation> QgsDiscoverRelationsDlg::relations() const

View File

@ -33,6 +33,10 @@ QgsRelationAddDlg::QgsRelationAddDlg( QWidget *parent )
mCbxReferencedLayer->setFilters( QgsMapLayerProxyModel::VectorLayer );
mCbxReferencedField->setLayer( mCbxReferencedLayer->currentLayer() );
mCbxRelationStrength->addItem( "Association", QVariant::fromValue( QgsRelation::RelationStrength::Association ) );
mCbxRelationStrength->addItem( "Composition", QVariant::fromValue( QgsRelation::RelationStrength::Composition ) );
mCbxRelationStrength->setToolTip( QStringLiteral( "Composition (child features will be copied too) or Association" ) );
mTxtRelationId->setPlaceholderText( tr( "[Generated automatically]" ) );
checkDefinitionValid();
@ -74,6 +78,10 @@ QString QgsRelationAddDlg::relationName()
return mTxtRelationName->text();
}
QgsRelation::RelationStrength QgsRelationAddDlg::relationStrength()
{
return mCbxRelationStrength->currentData().value<QgsRelation::RelationStrength>();
}
void QgsRelationAddDlg::checkDefinitionValid()
{

View File

@ -18,6 +18,7 @@
#include <QDialog>
#include "ui_qgsrelationadddlgbase.h"
#include "qgis_app.h"
#include "qgsrelation.h"
class QgsVectorLayer;
@ -33,7 +34,7 @@ class APP_EXPORT QgsRelationAddDlg : public QDialog, private Ui::QgsRelationAddD
QList< QPair< QString, QString > > references();
QString relationId();
QString relationName();
QgsRelation::RelationStrength relationStrength();
private slots:

View File

@ -77,6 +77,19 @@ void QgsRelationManagerDialog::addRelation( const QgsRelation &rel )
item = new QTableWidgetItem( rel.id() );
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 5, item );
if ( rel.strength() == QgsRelation::RelationStrength::Composition )
{
item = new QTableWidgetItem( QStringLiteral( "Composition" ) );
}
else
{
item = new QTableWidgetItem( QStringLiteral( "Association" ) );
}
item->setFlags( Qt::ItemIsEditable );
mRelationsTable->setItem( row, 6, item );
mRelationsTable->setSortingEnabled( true );
}
@ -116,6 +129,7 @@ void QgsRelationManagerDialog::mBtnAddRelation_clicked()
relation.setId( relationId );
relation.addFieldPair( addDlg.references().at( 0 ).first, addDlg.references().at( 0 ).second );
relation.setName( addDlg.relationName() );
relation.setStrength( addDlg.relationStrength() );
addRelation( relation );
}

View File

@ -36,6 +36,7 @@ QgsRelation QgsRelation::createFromXml( const QDomNode &node )
QString referencedLayerId = elem.attribute( QStringLiteral( "referencedLayer" ) );
QString id = elem.attribute( QStringLiteral( "id" ) );
QString name = elem.attribute( QStringLiteral( "name" ) );
QString strength = elem.attribute( QStringLiteral( "strength" ) );
const QMap<QString, QgsMapLayer *> &mapLayers = QgsProject::instance()->mapLayers();
@ -66,6 +67,14 @@ QgsRelation QgsRelation::createFromXml( const QDomNode &node )
relation.mReferencedLayer = qobject_cast<QgsVectorLayer *>( referencedLayer );
relation.mRelationId = id;
relation.mRelationName = name;
if ( strength == "Composition" )
{
relation.mRelationStrength = RelationStrength::Composition;
}
else
{
relation.mRelationStrength = RelationStrength::Association;
}
QDomNodeList references = elem.elementsByTagName( QStringLiteral( "fieldRef" ) );
for ( int i = 0; i < references.size(); ++i )
@ -90,6 +99,14 @@ void QgsRelation::writeXml( QDomNode &node, QDomDocument &doc ) const
elem.setAttribute( QStringLiteral( "name" ), mRelationName );
elem.setAttribute( QStringLiteral( "referencingLayer" ), mReferencingLayerId );
elem.setAttribute( QStringLiteral( "referencedLayer" ), mReferencedLayerId );
if ( mRelationStrength == RelationStrength::Composition )
{
elem.setAttribute( QStringLiteral( "strength" ), QStringLiteral( "Composition" ) );
}
else
{
elem.setAttribute( QStringLiteral( "strength" ), QStringLiteral( "Association" ) );
}
Q_FOREACH ( const FieldPair &fields, mFieldPairs )
{
@ -114,6 +131,12 @@ void QgsRelation::setName( const QString &name )
mRelationName = name;
}
void QgsRelation::setStrength( const RelationStrength &strength )
{
mRelationStrength = strength;
}
void QgsRelation::setReferencingLayer( const QString &id )
{
mReferencingLayerId = id;
@ -206,6 +229,11 @@ QString QgsRelation::name() const
return mRelationName;
}
QgsRelation::RelationStrength QgsRelation::strength() const
{
return mRelationStrength;
}
QString QgsRelation::id() const
{
return mRelationId;

View File

@ -48,6 +48,17 @@ class CORE_EXPORT QgsRelation
public:
/**
* enum for the relation strength
* Association, Composition
*/
enum RelationStrength
{
Association, //!< Loose relation, related elements are not part of the parent and a parent copy will not copy any children.
Composition //!< Fix relation, related elements are part of the parent and a parent copy will copy any children or delete of parent will delete children
};
#ifndef SIP_RUN
/**
@ -109,6 +120,12 @@ class CORE_EXPORT QgsRelation
*/
void setName( const QString &name );
/**
* Set a strength for this relation
* \since QGIS 3.0
*/
void setStrength( const RelationStrength &strength );
/**
* Set the referencing (child) layer id. This layer will be searched in the registry.
*/
@ -214,6 +231,14 @@ class CORE_EXPORT QgsRelation
*/
QString name() const;
/**
* Returns the relation strength as a string
*
* \returns strength
* \since QGIS 3.0
*/
RelationStrength strength() const;
/**
* A (project-wide) unique id for this relation
*
@ -345,6 +370,8 @@ class CORE_EXPORT QgsRelation
//! The parent layer
QgsVectorLayer *mReferencedLayer = nullptr;
RelationStrength mRelationStrength;
/**
* A list of fields which define the relation.
* In most cases there will be only one value, but multiple values
@ -357,5 +384,6 @@ class CORE_EXPORT QgsRelation
// Register QgsRelation for usage with QVariant
Q_DECLARE_METATYPE( QgsRelation )
Q_DECLARE_METATYPE( QgsRelation::RelationStrength )
#endif // QGSRELATION_H

View File

@ -16,6 +16,9 @@
#include "qgsvectorlayerutils.h"
#include "qgsvectordataprovider.h"
#include <QRegularExpression>
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include "qgslogger.h"
bool QgsVectorLayerUtils::valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds )
{
@ -320,3 +323,87 @@ QgsFeature QgsVectorLayerUtils::createFeature( QgsVectorLayer *layer, const QgsG
return newFeature;
}
QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext )
{
if ( !layer )
return QgsFeature();
if ( !layer->isEditable() )
return QgsFeature();
//get context from layer
QgsExpressionContext context = layer->createExpressionContext();
context.setFeature( feature );
//create the attribute map
QgsAttributes srcAttr = feature.attributes();
QgsAttributeMap dstAttr;
for ( int src = 0; src < srcAttr.count(); ++src )
{
dstAttr[ src ] = srcAttr.at( src );
}
QgsFeature newFeature = createFeature( layer, feature.geometry(), dstAttr, &context );
const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
for ( const QgsRelation &relation : relations )
{
//check if composition (and not association)
if ( relation.strength() == QgsRelation::Composition && depth < 1 )
{
depth++;
//get features connected over this relation
QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
QgsFeatureIds childFeatureIds;
QgsFeature childFeature;
while ( relatedFeaturesIt.nextFeature( childFeature ) )
{
//set childlayer editable
relation.referencingLayer()->startEditing();
//change the fk of the child to the id of the new parent
for ( const QgsRelation::FieldPair &fieldPair : relation.fieldPairs() )
{
childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
}
//call the function for the child
duplicateFeature( relation.referencingLayer(), childFeature, project, depth, duplicateFeatureContext );
//add the new feature id for feedback
childFeatureIds.insert( childFeature.id() );
}
//store for feedback
duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
}
}
layer->addFeature( newFeature );
return newFeature;
}
QList<QgsVectorLayer *> QgsVectorLayerUtils::QgsDuplicateFeatureContext::layers() const
{
QList<QgsVectorLayer *> layers;
QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
layers.append( i.key() );
return layers;
}
QgsFeatureIds QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicatedFeatures( QgsVectorLayer *layer ) const
{
return mDuplicatedFeatures[layer];
}
void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, QgsFeatureIds ids )
{
mDuplicatedFeatures.insert( layer, ids );
}
/*
QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
{
return mDuplicatedFeatures;
}
*/

View File

@ -32,6 +32,43 @@ class CORE_EXPORT QgsVectorLayerUtils
{
public:
/**
* \ingroup core
* \class QgsDuplicateFeatureContext
* \brief Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features
*
* \since QGIS 3.0
*/
class QgsDuplicateFeatureContext
{
public:
QgsDuplicateFeatureContext() {}
/**
* Returns all the layers in the member QMap mDuplicatedFeatures
* \since QGIS 3.0
*/
QList<QgsVectorLayer *> layers() const;
/**
* Returns the duplicated features in the given layer
* \since QGIS 3.0
*/
QgsFeatureIds duplicatedFeatures( QgsVectorLayer *layer ) const;
private:
QMap<QgsVectorLayer *, QgsFeatureIds> mDuplicatedFeatures;
friend class QgsVectorLayerUtils;
/**
* To set an entry to the member QMap mDuplicatedFeatures
* \since QGIS 3.0
*/
void setDuplicatedFeatures( QgsVectorLayer *layer, QgsFeatureIds ids );
};
/**
* Returns true if the specified value already exists within a field. This method can be used to test for uniqueness
* of values inside a layer's attributes. An optional list of ignored feature IDs can be provided, if so, any features
@ -68,6 +105,15 @@ class CORE_EXPORT QgsVectorLayerUtils
const QgsAttributeMap &attributes = QgsAttributeMap(),
QgsExpressionContext *context = nullptr );
/**
* Duplicates a feature and it's children (one level deep). It calls CreateFeature, so
* default values and constraints (e.g., unique constraints) will automatically be handled.
* The duplicated feature will be automatically inserted into the layer.
* \since QGIS 3.0
*/
static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext SIP_OUT );
};
#endif // QGSVECTORLAYERUTILS_H

View File

@ -62,6 +62,11 @@
<string>Referenced Field</string>
</property>
</column>
<column>
<property name="text">
<string>Strength</string>
</property>
</column>
</widget>
</item>
<item>

View File

@ -7,31 +7,60 @@
<x>0</x>
<y>0</y>
<width>581</width>
<height>267</height>
<height>342</height>
</rect>
</property>
<property name="windowTitle">
<string>Add Relation</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<item row="1" column="2">
<widget class="QgsMapLayerComboBox" name="mCbxReferencedLayer"/>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Referenced Field</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QgsFieldComboBox" name="mCbxReferencingField"/>
</item>
<item row="2" column="2">
<widget class="QgsFieldComboBox" name="mCbxReferencedField"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Referencing Layer (Child)</string>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QgsMapLayerComboBox" name="mCbxReferencingLayer"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QgsMapLayerComboBox" name="mCbxReferencingLayer"/>
<item row="0" column="2">
<widget class="QLineEdit" name="mTxtRelationName"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_5">
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Id</string>
<string>Referenced Layer (Parent)</string>
</property>
</widget>
</item>
<item row="15" column="0" colspan="3">
<item row="5" column="2" rowspan="2">
<widget class="QLineEdit" name="mTxtRelationId"/>
</item>
<item row="8" column="2">
<widget class="QDialogButtonBox" name="mButtonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -41,48 +70,29 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Referencing Layer (Child)</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QgsFieldComboBox" name="mCbxReferencingField"/>
</item>
<item row="5" column="0">
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Referencing Field</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<item row="7" column="0" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Referenced Layer (Parent)</string>
<string>Relationship Strength</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<item row="5" column="0" rowspan="2" colspan="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Referenced Field</string>
<string>Id</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QgsFieldComboBox" name="mCbxReferencedField"/>
</item>
<item row="9" column="1" colspan="2">
<widget class="QLineEdit" name="mTxtRelationId"/>
</item>
<item row="2" column="1" colspan="2">
<widget class="QgsMapLayerComboBox" name="mCbxReferencedLayer"/>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="mTxtRelationName"/>
<item row="7" column="2">
<widget class="QComboBox" name="mCbxRelationStrength"/>
</item>
</layout>
</widget>

View File

@ -43,21 +43,26 @@
<string>Referencing Field</string>
</property>
</column>
<column>
<property name="text">
<string>Referenced Layer</string>
</property>
</column>
<column>
<property name="text">
<string>Referenced Field</string>
</property>
</column>
<column>
<property name="text">
<string>Referenced Layer</string>
</property>
</column>
<column>
<property name="text">
<string>Id</string>
</property>
</column>
<column>
<property name="text">
<string>Strength</string>
</property>
</column>
</widget>
</item>
<item>

View File

@ -14,13 +14,16 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import (QgsVectorLayer,
from qgis.core import (QgsProject,
QgsVectorLayer,
QgsVectorLayerUtils,
QgsFieldConstraints,
QgsFeature,
QgsFeatureIterator,
QgsGeometry,
QgsPointXY,
QgsDefaultValue,
QgsRelation,
NULL
)
from qgis.testing import start_app, unittest
@ -267,6 +270,159 @@ class TestQgsVectorLayerUtils(unittest.TestCase):
f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123})
self.assertEqual(f.attributes(), ['test_4', 128, NULL])
def testDuplicateFeature(self):
""" test duplicating a feature """
project = QgsProject().instance()
# LAYERS
# - add first layer (parent)
layer1 = QgsVectorLayer("Point?field=fldtxt:string&field=pkid:integer",
"parentlayer", "memory")
# > check first layer (parent)
self.assertTrue(layer1.isValid())
# - set the value for the copy
layer1.setDefaultValueDefinition(1, QgsDefaultValue("rand(1000,2000)"))
# > check first layer (parent)
self.assertTrue(layer1.isValid())
# - add second layer (child)
layer2 = QgsVectorLayer("Point?field=fldtxt:string&field=id:integer&field=foreign_key:integer",
"childlayer", "memory")
# > check second layer (child)
self.assertTrue(layer2.isValid())
# - add layers
project.addMapLayers([layer1, layer2])
# FEATURES
# - add 2 features on layer1 (parent)
l1f1orig = QgsFeature()
l1f1orig.setFields(layer1.fields())
l1f1orig.setAttributes(["F_l1f1", 100])
l1f2orig = QgsFeature()
l1f2orig.setFields(layer1.fields())
l1f2orig.setAttributes(["F_l1f2", 101])
# > check by adding features
self.assertTrue(layer1.dataProvider().addFeatures([l1f1orig, l1f2orig]))
# add 4 features on layer2 (child)
l2f1orig = QgsFeature()
l2f1orig.setFields(layer2.fields())
l2f1orig.setAttributes(["F_l2f1", 201, 100])
l2f2orig = QgsFeature()
l2f2orig.setFields(layer2.fields())
l2f2orig.setAttributes(["F_l2f2", 202, 100])
l2f3orig = QgsFeature()
l2f3orig.setFields(layer2.fields())
l2f3orig.setAttributes(["F_l2f3", 203, 100])
l2f4orig = QgsFeature()
l2f4orig.setFields(layer2.fields())
l2f4orig.setAttributes(["F_l2f4", 204, 101])
# > check by adding features
self.assertTrue(layer2.dataProvider().addFeatures([l2f1orig, l2f2orig, l2f3orig, l2f4orig]))
# RELATION
# - create the relationmanager
relMgr = project.relationManager()
# - create the relation
rel = QgsRelation()
rel.setId('rel1')
rel.setName('childrel')
rel.setReferencingLayer(layer2.id())
rel.setReferencedLayer(layer1.id())
rel.addFieldPair('foreign_key', 'pkid')
rel.setStrength(QgsRelation.Composition)
# > check relation
self.assertTrue(rel.isValid())
# - add relation
relMgr.addRelation(rel)
# > check if referencedLayer is layer1
self.assertEqual(rel.referencedLayer(), layer1)
# > check if referencingLayer is layer2
self.assertEqual(rel.referencingLayer(), layer2)
# > check if the layers are correct in relation when loading from relationManager
relations = project.relationManager().relations()
relation = relations[list(relations.keys())[0]]
# > check if referencedLayer is layer1
self.assertEqual(relation.referencedLayer(), layer1)
# > check if referencingLayer is layer2
self.assertEqual(relation.referencingLayer(), layer2)
# > check the relatedfeatures
'''
# testoutput 1
print( "\nAll Features and relations")
featit=layer1.getFeatures()
f=QgsFeature()
while featit.nextFeature(f):
print( f.attributes())
childFeature = QgsFeature()
relfeatit=rel.getRelatedFeatures(f)
while relfeatit.nextFeature(childFeature):
print( childFeature.attributes() )
print( "\n--------------------------")
print( "\nFeatures on layer1")
for f in layer1.getFeatures():
print( f.attributes() )
print( "\nFeatures on layer2")
for f in layer2.getFeatures():
print( f.attributes() )
'''
# DUPLICATION
# - duplicate feature l1f1orig with children
layer1.startEditing()
results = QgsVectorLayerUtils.duplicateFeature(layer1, l1f1orig, project, 0)
# > check if name is name of duplicated (pk is different)
result_feature = results[0]
self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt'))
# > check duplicated child layer
result_layer = results[1].layers()[0]
self.assertEqual(result_layer, layer2)
# > check duplicated child features
self.assertTrue(results[1].duplicatedFeatures(result_layer))
'''
# testoutput 2
print( "\nFeatures on layer1 (after duplication)")
for f in layer1.getFeatures():
print( f.attributes() )
print( "\nFeatures on layer2 (after duplication)")
for f in layer2.getFeatures():
print( f.attributes() )
print( "\nAll Features and relations")
featit=layer1.getFeatures()
f=QgsFeature()
while featit.nextFeature(f):
print( f.attributes())
childFeature = QgsFeature()
relfeatit=rel.getRelatedFeatures(f)
while relfeatit.nextFeature(childFeature):
print( childFeature.attributes() )
'''
# > compare text of parent feature
self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt'))
# - create copyValueList
childFeature = QgsFeature()
relfeatit = rel.getRelatedFeatures(result_feature)
copyValueList = []
while relfeatit.nextFeature(childFeature):
copyValueList.append(childFeature.attribute('fldtxt'))
# - create origValueList
childFeature = QgsFeature()
relfeatit = rel.getRelatedFeatures(l1f1orig)
origValueList = []
while relfeatit.nextFeature(childFeature):
origValueList.append(childFeature.attribute('fldtxt'))
# - check if the ids are still the same
self.assertEqual(copyValueList, origValueList)
if __name__ == '__main__':
unittest.main()