Skip to content
Permalink
Browse files

get all the child and join features of the first level to create the …

…warning text to inform the user that there is a cascade delete or a composition relation
  • Loading branch information
signedav committed May 8, 2020
1 parent de6aed6 commit 652cc99798b5a7c06008a2888bc7f14fc9461c14
@@ -297,7 +297,7 @@ The following operations will be performed to convert the input features:
.. versionadded:: 3.12
%End

static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsProject *project );
static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context );
%Docstring

:return: true if the ``is`` connected as parent in at least one composition relation of the ``project``
@@ -9001,11 +9001,21 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFea
}
}

if ( QgsVectorLayerUtils::impactsCascadeFeatures( vlayer, QgsProject::instance() ) )
QgsVectorLayerUtils::QgsDuplicateFeatureContext infoContext;
if ( QgsVectorLayerUtils::impactsCascadeFeatures( vlayer, vlayer->selectedFeatureIds(), QgsProject::instance(), infoContext ) )
{
QString childrenInfo;
int childrenCount = 0;
const auto infoContextLayers = infoContext.layers();
for ( QgsVectorLayer *chl : infoContextLayers )
{
childrenCount += infoContext.duplicatedFeatures( chl ).size();
childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
}

// for extra safety to make sure we know that the delete can have impact on children and joins
int res = QMessageBox::question( mMapCanvas, tr( "Possible impact on descendants of layer \"%1\"" ).arg( vlayer->name() ),
tr( "A delete on this layer could have an impact on referencing or joined layers and their descendants. Would you still like to continue?" ),
int res = QMessageBox::question( mMapCanvas, tr( "Delete at least %3 feature(s) on other layer(s)" ).arg( childrenCount ),
tr( "Delete %1 feature(s) on layer \"%2\" and %3as well.\nAnd all the further descendants of them.\nDelete these features?" ).arg( numberOfSelectedFeatures ).arg( vlayer->name() ).arg( childrenInfo ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
return;
@@ -864,11 +864,22 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )
{
QgsDebugMsg( QStringLiteral( "Delete %1" ).arg( fid ) );
if ( QgsVectorLayerUtils::impactsCascadeFeatures( mLayer, QgsProject::instance() ) )

QgsVectorLayerUtils::QgsDuplicateFeatureContext infoContext;
if ( QgsVectorLayerUtils::impactsCascadeFeatures( mLayer, QgsFeatureIds() << fid, QgsProject::instance(), infoContext ) )
{
QString childrenInfo;
int childrenCount = 0;
const auto infoContextLayers = infoContext.layers();
for ( QgsVectorLayer *chl : infoContextLayers )
{
childrenCount += infoContext.duplicatedFeatures( chl ).size();
childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
}

// for extra safety to make sure we know that the delete can have impact on children and joins
int res = QMessageBox::question( this, tr( "Possible impact on descendants of layer \"%1\"" ).arg( mLayer->name() ),
tr( "A delete on this layer could have an impact on referencing or joined layers and their descendants. Would you still like to continue?" ),
int res = QMessageBox::question( this, tr( "Delete at least %3 feature(s) on other layer(s)" ).arg( childrenCount ),
tr( "Delete of feature on layer \"%2\" and %3as well.\nAnd all the further descendants of them.\nDelete these features?" ).arg( mLayer->name() ).arg( childrenInfo ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
return;
@@ -935,7 +935,7 @@ QString QgsVectorLayerUtils::getFeatureDisplayString( const QgsVectorLayer *laye
return displayString;
}

bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsProject *project )
bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context )
{
if ( !layer )
return false;
@@ -945,19 +945,72 @@ bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, c
{
if ( relation.strength() == QgsRelation::Composition )
{
return true;
QgsFeatureIds childFeatureIds;

const auto constFids = fids;
for ( const QgsFeatureId fid : constFids )
{
//get features connected over this relation
QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
QgsFeature childFeature;
while ( relatedFeaturesIt.nextFeature( childFeature ) )
{
childFeatureIds.insert( childFeature.id() );
}
}

if ( childFeatureIds.count() > 0 )
{
if ( context.layers().contains( relation.referencingLayer() ) )
{
QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
// add feature ids
handledFeatureIds.unite( childFeatureIds );
context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
}
else
{
// add layer and feature id
context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
}
}
}
}

layer->joinBuffer()->containsJoins();
const auto constVectorJoins = layer->joinBuffer()->vectorJoins();
for ( const QgsVectorLayerJoinInfo &info : constVectorJoins )
if ( layer->joinBuffer()->containsJoins() )
{
if ( info.isEditable() && info.hasCascadedDelete() )
const auto constVectorJoins = layer->joinBuffer()->vectorJoins();
for ( const QgsVectorLayerJoinInfo &info : constVectorJoins )
{
return true;
if ( info.isEditable() && info.hasCascadedDelete() )
{
QgsFeatureIds joinFeatureIds;
const auto constFids = fids;
for ( const QgsFeatureId &fid : constFids )
{
const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
if ( joinFeature.isValid() )
joinFeatureIds.insert( joinFeature.id() );
}

if ( joinFeatureIds.count() > 0 )
{
if ( context.layers().contains( info.joinLayer() ) )
{
QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
// add feature ids
handledFeatureIds.unite( joinFeatureIds );
context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
}
else
{
// add layer and feature id
context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
}
}
}
}
}

return false;
return context.layers().count();
}
@@ -326,7 +326,7 @@ class CORE_EXPORT QgsVectorLayerUtils
*
* \since QGIS 3.14
*/
static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsProject *project );
static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context );

};

@@ -728,13 +728,23 @@ void QgsRelationEditorWidget::deleteFeatures( const QgsFeatureIds &featureids )
layer = mRelation.referencingLayer();
}

if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, QgsProject::instance() ) )
QgsVectorLayerUtils::QgsDuplicateFeatureContext infoContext;
if ( QgsVectorLayerUtils::impactsCascadeFeatures( layer, featureids, QgsProject::instance(), infoContext ) )
{
QString childrenInfo;
int childrenCount = 0;
const auto infoContextLayers = infoContext.layers();
for ( QgsVectorLayer *chl : infoContextLayers )
{
childrenCount += infoContext.duplicatedFeatures( chl ).size();
childrenInfo += ( tr( "%1 feature(s) on layer \"%2\", " ).arg( infoContext.duplicatedFeatures( chl ).size() ).arg( chl->name() ) );
}

// for extra safety to make sure we know that the delete can have impact on children and joins
int res = QMessageBox::question( this, tr( "Possible impact on descendants of layer \"%1\"" ).arg( layer->name() ),
tr( "A delete on this layer could have an impact on referencing or joined layers and their descendants. Would you still like to continue?" ),
int res = QMessageBox::question( this, tr( "Delete at least %3 feature(s) on other layer(s)" ).arg( childrenCount ),
tr( "Delete %1 feature(s) on layer \"%2\" and %3as well.\nAnd all the further descendants of them.\nDelete these features?" ).arg( featureids.count() ).arg( layer->name() ).arg( childrenInfo ),
QMessageBox::Yes | QMessageBox::No );
if ( res == QMessageBox::No )
if ( res != QMessageBox::Yes )
deleteFeatures = false;
}

0 comments on commit 652cc99

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