mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
fix duplication of feature being stopped at 1 level deep (#39550)
This commit is contained in:
parent
cf37cb94f3
commit
9db2d79244
@ -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``.
|
||||
|
@ -16478,7 +16478,7 @@ QgsFeature QgisApp::duplicateFeatures( QgsMapLayer *mlayer, const QgsFeature &fe
|
||||
{
|
||||
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();
|
||||
@ -16529,7 +16529,7 @@ QgsFeature QgisApp::duplicateFeatureDigitized( QgsMapLayer *mlayer, const QgsFea
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user