Skip to content

Commit

Permalink
on deleting a feature, it deletes the relating children, when "cascad…
Browse files Browse the repository at this point in the history
…e" parameter is true, the relation strength is a composition.

"cascade" parameter is true on every "normal" delete fired by the user interface. It's not true, on functions like merge feature or offline editing synchronization etc.
  • Loading branch information
signedav committed May 7, 2020
1 parent 9cc2496 commit f352793
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 32 deletions.
13 changes: 10 additions & 3 deletions python/core/auto_generated/qgsvectorlayer.sip.in
Expand Up @@ -1259,10 +1259,13 @@ Deletes a vertex from a feature.
.. versionadded:: 2.14
%End

bool deleteSelectedFeatures( int *deletedCount = 0 );
bool deleteSelectedFeatures( int *deletedCount = 0, const bool cascade = false );
%Docstring
Deletes the selected features

:param deleteCount: The number of successfully deleted features
:param cascade: If the decendants of the feature should be deleted as well

:return: ``True`` in case of success and ``False`` otherwise
%End

Expand Down Expand Up @@ -1941,10 +1944,13 @@ Deletes a list of attribute fields (but does not commit it)
virtual bool addFeatures( QgsFeatureList &features, QgsFeatureSink::Flags flags = 0 ) ${SIP_FINAL};


bool deleteFeature( QgsFeatureId fid );
bool deleteFeature( QgsFeatureId fid, const bool cascade = false );
%Docstring
Deletes a feature from the layer (but does not commit it).

:param fid: The feature id to delete
:param cascade: If the decendants of the feature should be deleted as well

.. note::

Calls to deleteFeature() are only valid for layers in which edits have been enabled
Expand All @@ -1953,11 +1959,12 @@ Deletes a feature from the layer (but does not commit it).
changes can be discarded by calling rollBack().
%End

bool deleteFeatures( const QgsFeatureIds &fids );
bool deleteFeatures( const QgsFeatureIds &fids, const bool cascade = false );
%Docstring
Deletes a set of features from the layer (but does not commit it)

:param fids: The feature ids to delete
:param cascade: If the decendants of the feature should be deleted as well

:return: ``False`` if the layer is not in edit mode or does not support deleting
in case of an active transaction depends on the provider implementation
Expand Down
4 changes: 2 additions & 2 deletions python/core/auto_generated/qgsvectorlayerjoinbuffer.sip.in
Expand Up @@ -207,7 +207,7 @@ created if its fields are not empty.
.. versionadded:: 3.0
%End

bool deleteFeature( QgsFeatureId fid ) const;
bool deleteFeature( QgsFeatureId fid, const bool cascade = false ) const;
%Docstring
Deletes a feature from joined layers. The feature id given in
parameter is the one coming from the target layer.
Expand All @@ -220,7 +220,7 @@ parameter is the one coming from the target layer.
.. versionadded:: 3.0
%End

bool deleteFeatures( const QgsFeatureIds &fids ) const;
bool deleteFeatures( const QgsFeatureIds &fids, const bool cascade = false ) const;
%Docstring
Deletes a list of features from joined layers. Feature ids given
in a parameter are those coming from the target layer.
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.cpp
Expand Up @@ -9003,7 +9003,7 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFea

vlayer->beginEditCommand( tr( "Features deleted" ) );
int deletedCount = 0;
if ( !vlayer->deleteSelectedFeatures( &deletedCount ) )
if ( !vlayer->deleteSelectedFeatures( &deletedCount, true ) )
{
visibleMessageBar()->pushMessage( tr( "Problem deleting features" ),
tr( "A problem occurred during deletion from layer \"%1\". %n feature(s) not deleted.", nullptr, numberOfSelectedFeatures - deletedCount ).arg( vlayer->name() ),
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsattributetabledialog.cpp
Expand Up @@ -864,7 +864,7 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )
{
QgsDebugMsg( QStringLiteral( "Delete %1" ).arg( fid ) );
mLayer->deleteFeature( fid );
mLayer->deleteFeature( fid, true );
}

void QgsAttributeTableDialog::showContextMenu( QgsActionMenu *menu, const QgsFeatureId fid )
Expand Down
42 changes: 34 additions & 8 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -1140,7 +1140,7 @@ QgsVectorLayer::EditResult QgsVectorLayer::deleteVertex( QgsFeatureId featureId,
}


bool QgsVectorLayer::deleteSelectedFeatures( int *deletedCount )
bool QgsVectorLayer::deleteSelectedFeatures( int *deletedCount, const bool cascade )
{
if ( !mValid || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
{
Expand All @@ -1159,7 +1159,7 @@ bool QgsVectorLayer::deleteSelectedFeatures( int *deletedCount )
const auto constSelectedFeatures = selectedFeatures;
for ( QgsFeatureId fid : constSelectedFeatures )
{
deleted += deleteFeature( fid ); // removes from selection
deleted += deleteFeature( fid, cascade ); // removes from selection
}

triggerRepaint();
Expand Down Expand Up @@ -3164,25 +3164,51 @@ bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
return deleted;
}

bool QgsVectorLayer::deleteFeatureWithDependencies( QgsFeatureId fid )
bool QgsVectorLayer::deleteFeatureWithDependencies( QgsFeatureId fid, const bool cascade )
{
if ( !mEditBuffer )
return false;

if ( cascade )
{

const QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( this );

for ( const QgsRelation &relation : relations )
{
//check if composition (and not association)
if ( relation.strength() == QgsRelation::Composition )
{
//get features connected over this relation
QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
QgsFeatureIds childFeatureIds;
QgsFeature childFeature;
while ( relatedFeaturesIt.nextFeature( childFeature ) )
{
childFeatureIds.insert( childFeature.id() );
}

//set childlayer editable
relation.referencingLayer()->startEditing();
relation.referencingLayer()->deleteFeatures( childFeatureIds );
}
}
}

if ( mJoinBuffer->containsJoins() )
mJoinBuffer->deleteFeature( fid );
mJoinBuffer->deleteFeature( fid, cascade );

bool res = mEditBuffer->deleteFeature( fid );

return res;
}

bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
bool QgsVectorLayer::deleteFeature( QgsFeatureId fid, const bool cascade )
{
if ( !mEditBuffer )
return false;

bool res = deleteFeatureWithDependencies( fid );
bool res = deleteFeatureWithDependencies( fid, cascade );

if ( res )
{
Expand All @@ -3193,12 +3219,12 @@ bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
return res;
}

bool QgsVectorLayer::deleteFeatures( const QgsFeatureIds &fids )
bool QgsVectorLayer::deleteFeatures( const QgsFeatureIds &fids, const bool cascade )
{
bool res = true;
const auto constFids = fids;
for ( QgsFeatureId fid : constFids )
res = deleteFeatureWithDependencies( fid ) && res;
res = deleteFeatureWithDependencies( fid, cascade ) && res;

if ( res )
{
Expand Down
16 changes: 11 additions & 5 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1278,9 +1278,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte

/**
* Deletes the selected features
* \returns TRUE in case of success and FALSE otherwise
* \param deleteCount The number of successfully deleted features
* \param cascade If the decendants of the feature should be deleted as well
*
* \returns TRUE in case of success and FALSE otherwise
*/
Q_INVOKABLE bool deleteSelectedFeatures( int *deletedCount = nullptr );
Q_INVOKABLE bool deleteSelectedFeatures( int *deletedCount = nullptr, const bool cascade = false );

/**
* Adds a ring to polygon/multipolygon features
Expand Down Expand Up @@ -1812,17 +1815,20 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte

/**
* Deletes a feature from the layer (but does not commit it).
* \param fid The feature id to delete
* \param cascade If the decendants of the feature should be deleted as well
*
* \note Calls to deleteFeature() are only valid for layers in which edits have been enabled
* by a call to startEditing(). Changes made to features using this method are not committed
* to the underlying data provider until a commitChanges() call is made. Any uncommitted
* changes can be discarded by calling rollBack().
*/
bool deleteFeature( QgsFeatureId fid );
bool deleteFeature( QgsFeatureId fid, const bool cascade = false );

/**
* Deletes a set of features from the layer (but does not commit it)
* \param fids The feature ids to delete
* \param cascade If the decendants of the feature should be deleted as well
*
* \returns FALSE if the layer is not in edit mode or does not support deleting
* in case of an active transaction depends on the provider implementation
Expand All @@ -1832,7 +1838,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* to the underlying data provider until a commitChanges() call is made. Any uncommitted
* changes can be discarded by calling rollBack().
*/
bool deleteFeatures( const QgsFeatureIds &fids );
bool deleteFeatures( const QgsFeatureIds &fids, const bool cascade = false );

/**
* Attempts to commit to the underlying data provider any buffered changes made since the
Expand Down Expand Up @@ -2689,7 +2695,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
//! Read simple labeling from layer's custom properties (QGIS 2.x projects)
QgsAbstractVectorLayerLabeling *readLabelingFromCustomProperties();

bool deleteFeatureWithDependencies( QgsFeatureId fid );
bool deleteFeatureWithDependencies( QgsFeatureId fid, const bool cascade = false );

#ifdef SIP_RUN
QgsVectorLayer( const QgsVectorLayer &rhs );
Expand Down
8 changes: 4 additions & 4 deletions src/core/qgsvectorlayerjoinbuffer.cpp
Expand Up @@ -663,12 +663,12 @@ bool QgsVectorLayerJoinBuffer::changeAttributeValues( QgsFeatureId fid, const Qg
return success;
}

bool QgsVectorLayerJoinBuffer::deleteFeature( QgsFeatureId fid ) const
bool QgsVectorLayerJoinBuffer::deleteFeature( QgsFeatureId fid, const bool cascade ) const
{
return deleteFeatures( QgsFeatureIds() << fid );
return deleteFeatures( QgsFeatureIds() << fid, cascade );
}

bool QgsVectorLayerJoinBuffer::deleteFeatures( const QgsFeatureIds &fids ) const
bool QgsVectorLayerJoinBuffer::deleteFeatures( const QgsFeatureIds &fids, const bool cascade ) const
{
if ( !containsJoins() )
return false;
Expand All @@ -683,7 +683,7 @@ bool QgsVectorLayerJoinBuffer::deleteFeatures( const QgsFeatureIds &fids ) const
{
const QgsFeature joinFeature = joinedFeatureOf( &info, mLayer->getFeature( fid ) );
if ( joinFeature.isValid() )
info.joinLayer()->deleteFeature( joinFeature.id() );
info.joinLayer()->deleteFeature( joinFeature.id(), cascade );
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsvectorlayerjoinbuffer.h
Expand Up @@ -202,7 +202,7 @@ class CORE_EXPORT QgsVectorLayerJoinBuffer : public QObject, public QgsFeatureSi
*
* \since QGIS 3.0
*/
bool deleteFeature( QgsFeatureId fid ) const;
bool deleteFeature( QgsFeatureId fid, const bool cascade = false ) const;

/**
* Deletes a list of features from joined layers. Feature ids given
Expand All @@ -214,7 +214,7 @@ class CORE_EXPORT QgsVectorLayerJoinBuffer : public QObject, public QgsFeatureSi
*
* \since QGIS 3.0
*/
bool deleteFeatures( const QgsFeatureIds &fids ) const;
bool deleteFeatures( const QgsFeatureIds &fids, const bool cascade = false ) const;

signals:

Expand Down
10 changes: 4 additions & 6 deletions src/gui/qgsrelationeditorwidget.cpp
Expand Up @@ -667,10 +667,8 @@ void QgsRelationEditorWidget::deleteFeatures( const QgsFeatureIds &featureids )
// When deleting a linked feature within an N:M relation,
// check if the feature is linked to more than just one feature.
// In case it is linked more than just once, ask the user for confirmation
// as it is likely he was not aware of the implications and might either
// leave the dataset in a corrupted state (referential integrity) or if
// the fk constraint is ON CASCADE DELETE, there may be several linking
// entries deleted along.
// as it is likely he was not aware of the implications and might delete
// there may be several linking entries deleted along.

QgsFeatureRequest deletedFeaturesRequest;
deletedFeaturesRequest.setFilterFids( featureids );
Expand Down Expand Up @@ -732,7 +730,7 @@ void QgsRelationEditorWidget::deleteFeatures( const QgsFeatureIds &featureids )

if ( deleteFeatures )
{
layer->deleteFeatures( featureids );
layer->deleteFeatures( featureids, true );
updateUi();
}
}
Expand Down Expand Up @@ -793,7 +791,7 @@ void QgsRelationEditorWidget::unlinkFeatures( const QgsFeatureIds &featureids )
QgsDebugMsgLevel( FID_TO_STRING( f.id() ), 4 );
}

mRelation.referencingLayer()->deleteFeatures( fids );
mRelation.referencingLayer()->deleteFeatures( fids, false );

updateUi();
}
Expand Down

0 comments on commit f352793

Please sign in to comment.