Skip to content
Permalink
Browse files

fix duplication of feature being stopped at 1 level deep (#39550)

  • Loading branch information
3nids committed Oct 26, 2020
1 parent cf37cb9 commit 9db2d79244f0b5065564e5c1247864a06a033c3f
@@ -204,18 +204,21 @@ automatically inserted into the layer.
.. versionadded:: 3.6
%End

static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext /Out/ );
static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext /Out/, const int maxDepth = 0 );
%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.
``depth`` the higher this number the deeper the level - With depth > 0 the children of the feature are not duplicated
``duplicateFeatureContext`` stores all the layers and the featureids of the duplicated features (incl. children)
``maxDepth`` the maximum depth to duplicate children in relations, 0 is unlimited depth (in any case, limited to 100)
``depth`` the current depth, not exposed in Python
``referencedLayersBranch`` the current branch of layers across the relations, not exposed in Python, taken by copy not reference, used to avoid infinite loop

.. versionadded:: 3.0
%End



static void matchAttributesToFields( QgsFeature &feature, const QgsFields &fields );
%Docstring
Matches the attributes in ``feature`` to the specified ``fields``.
{
QgsVectorLayerUtils::QgsDuplicateFeatureContext duplicateFeatureContext;

QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), 0, duplicateFeatureContext );
QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicateFeatureContext );
featureCount += 1;

const auto duplicatedFeatureContextLayers = duplicateFeatureContext.layers();

QgsFeature newFeature = feature;
newFeature.setGeometry( digitizedFeature.geometry() );
QgsVectorLayerUtils::duplicateFeature( layer, newFeature, QgsProject::instance(), 0, duplicateFeatureContext );
QgsVectorLayerUtils::duplicateFeature( layer, newFeature, QgsProject::instance(), duplicateFeatureContext );

QString childrenInfo;
const auto duplicateFeatureContextLayers = duplicateFeatureContext.layers();
@@ -42,6 +42,7 @@
#include "qgsstyle.h"
#include "qgsauxiliarystorage.h"


QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
{
std::unique_ptr<QgsExpression> expression;
@@ -622,7 +623,7 @@ QgsFeatureList QgsVectorLayerUtils::createFeatures( const QgsVectorLayer *layer,
return result;
}

QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext )
QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
{
if ( !layer )
return QgsFeature();
@@ -639,12 +640,16 @@ QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const Q

const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );

const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;

for ( const QgsRelation &relation : relations )
{
//check if composition (and not association)
if ( relation.strength() == QgsRelation::Composition && depth < 1 )
if ( relation.strength() == QgsRelation::Composition && !referencedLayersBranch.contains( relation.referencedLayer() ) && depth < effectiveMaxDepth )
{
depth++;
referencedLayersBranch << layer;

//get features connected over this relation
QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
QgsFeatureIds childFeatureIds;
@@ -660,7 +665,7 @@ QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const Q
childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
}
//call the function for the child
childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, depth, duplicateFeatureContext ).id() );
childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth, referencedLayersBranch ).id() );
}

//store for feedback
@@ -827,7 +832,10 @@ QgsFeatureIds QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicatedFeature

void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
{
mDuplicatedFeatures.insert( layer, ids );
if ( mDuplicatedFeatures.contains( layer ) )
mDuplicatedFeatures[layer] += ids;
else
mDuplicatedFeatures.insert( layer, ids );
}
/*
QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
@@ -205,11 +205,14 @@ class CORE_EXPORT QgsVectorLayerUtils
* 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.
* \a depth the higher this number the deeper the level - With depth > 0 the children of the feature are not duplicated
* \a duplicateFeatureContext stores all the layers and the featureids of the duplicated features (incl. children)
* \a maxDepth the maximum depth to duplicate children in relations, 0 is unlimited depth (in any case, limited to 100)
* \a depth the current depth, not exposed in Python
* \a referencedLayersBranch the current branch of layers across the relations, not exposed in Python, taken by copy not reference, used to avoid infinite loop
* \since QGIS 3.0
*/
static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, int depth, QgsDuplicateFeatureContext &duplicateFeatureContext SIP_OUT );
static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext SIP_OUT, const int maxDepth = 0, int depth SIP_PYARGREMOVE = 0, QList<QgsVectorLayer *> referencedLayersBranch SIP_PYARGREMOVE = QList<QgsVectorLayer *>() );


/**
* Gets the feature source from a QgsVectorLayer pointer.
@@ -637,7 +637,7 @@ void QgsRelationEditorWidget::duplicateFeature()
while ( fit.nextFeature( f ) )
{
QgsVectorLayerUtils::QgsDuplicateFeatureContext duplicatedFeatureContext;
QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), 0, duplicatedFeatureContext );
QgsVectorLayerUtils::duplicateFeature( layer, f, QgsProject::instance(), duplicatedFeatureContext );
}
}

0 comments on commit 9db2d79

Please sign in to comment.
You can’t perform that action at this time.