Skip to content

Commit

Permalink
Don't show cascaded feature deletion warnings and feedback if
Browse files Browse the repository at this point in the history
joined deleted features came from an auxilary layer

As auxiliary features are intended to be intrinsicly linked to
a normal layer's features, we don't need to warn or advise when
these are deleted alongside their parent feature.
  • Loading branch information
nyalldawson committed Oct 15, 2020
1 parent d87d230 commit 8c79b94
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 14 deletions.
12 changes: 11 additions & 1 deletion python/core/auto_generated/qgsvectorlayer.sip.in
Expand Up @@ -391,8 +391,18 @@ Constructor for LayerOptions.
Constructor for DeleteContext.
%End

QList<QgsVectorLayer *> handledLayers() const;
QList<QgsVectorLayer *> handledLayers( bool includeAuxiliaryLayers = true ) const;
%Docstring
Returns a list of all layers affected by the delete operation.

If ``includeAuxiliaryLayers`` is ``False`` then auxiliary layers will not be included in the
returned list.
%End

QgsFeatureIds handledFeatures( QgsVectorLayer *layer ) const;
%Docstring
Returns a list of feature IDs from the specified ``layer`` affected by the delete operation.
%End

bool cascade;
QgsProject *project;
Expand Down
9 changes: 8 additions & 1 deletion python/core/auto_generated/qgsvectorlayerutils.sip.in
Expand Up @@ -299,7 +299,14 @@ The following operations will be performed to convert the input features:
.. versionadded:: 3.12
%End

static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context /Out/ );
enum CascadedFeatureFlag
{
IgnoreAuxiliaryLayers,
};
typedef QFlags<QgsVectorLayerUtils::CascadedFeatureFlag> CascadedFeatureFlags;


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

:return: ``True`` if at least one feature of the ``fids`` on ``layer`` is connected as parent in at
Expand Down
6 changes: 3 additions & 3 deletions src/app/qgisapp.cpp
Expand Up @@ -9245,7 +9245,7 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFea
}

QgsVectorLayerUtils::QgsDuplicateFeatureContext infoContext;
if ( QgsVectorLayerUtils::impactsCascadeFeatures( vlayer, vlayer->selectedFeatureIds(), QgsProject::instance(), infoContext ) )
if ( QgsVectorLayerUtils::impactsCascadeFeatures( vlayer, vlayer->selectedFeatureIds(), QgsProject::instance(), infoContext, QgsVectorLayerUtils::IgnoreAuxiliaryLayers ) )
{
QString childrenInfo;
int childrenCount = 0;
Expand Down Expand Up @@ -9275,8 +9275,8 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFea
}
else
{
const auto contextLayers = context.handledLayers();
// if it affects more than one layer, print feedback for all descendants
const QList<QgsVectorLayer *> contextLayers = context.handledLayers( false );
// if it affects more than one non-auxiliary layer, print feedback for all descendants
if ( contextLayers.size() > 1 )
{
deletedCount = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/app/qgsattributetabledialog.cpp
Expand Up @@ -926,7 +926,7 @@ void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )
QgsDebugMsg( QStringLiteral( "Delete %1" ).arg( fid ) );

QgsVectorLayerUtils::QgsDuplicateFeatureContext infoContext;
if ( QgsVectorLayerUtils::impactsCascadeFeatures( mLayer, QgsFeatureIds() << fid, QgsProject::instance(), infoContext ) )
if ( QgsVectorLayerUtils::impactsCascadeFeatures( mLayer, QgsFeatureIds() << fid, QgsProject::instance(), infoContext, QgsVectorLayerUtils::IgnoreAuxiliaryLayers ) )
{
QString childrenInfo;
int childrenCount = 0;
Expand All @@ -947,7 +947,7 @@ void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )

QgsVectorLayer::DeleteContext context( true, QgsProject::instance() );
mLayer->deleteFeature( fid, &context );
const auto contextLayers = context.handledLayers();
const QList<QgsVectorLayer *> contextLayers = context.handledLayers( false );
//if it effected more than one layer, print feedback for all descendants
if ( contextLayers.size() > 1 )
{
Expand Down
7 changes: 5 additions & 2 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -5614,12 +5614,15 @@ void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name
}
}

QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers() const
QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers( bool includeAuxiliaryLayers ) const
{
QList<QgsVectorLayer *> layers;
QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
layers.append( i.key() );
{
if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
layers.append( i.key() );
}
return layers;
}

Expand Down
12 changes: 11 additions & 1 deletion src/core/qgsvectorlayer.h
Expand Up @@ -516,7 +516,17 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
*/
explicit DeleteContext( bool cascade = false, QgsProject *project = nullptr ): cascade( cascade ), project( project ) {}

QList<QgsVectorLayer *> handledLayers() const;
/**
* Returns a list of all layers affected by the delete operation.
*
* If \a includeAuxiliaryLayers is FALSE then auxiliary layers will not be included in the
* returned list.
*/
QList<QgsVectorLayer *> handledLayers( bool includeAuxiliaryLayers = true ) const;

/**
* Returns a list of feature IDs from the specified \a layer affected by the delete operation.
*/
QgsFeatureIds handledFeatures( QgsVectorLayer *layer ) const;

QMap<QgsVectorLayer *, QgsFeatureIds> mHandledFeatures SIP_SKIP;
Expand Down
10 changes: 7 additions & 3 deletions src/core/qgsvectorlayerutils.cpp
Expand Up @@ -40,6 +40,7 @@
#include "qgssymbollayer.h"
#include "qgsstyleentityvisitor.h"
#include "qgsstyle.h"
#include "qgsauxiliarystorage.h"

QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
{
Expand Down Expand Up @@ -971,7 +972,7 @@ QString QgsVectorLayerUtils::getFeatureDisplayString( const QgsVectorLayer *laye
return displayString;
}

bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context )
bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, CascadedFeatureFlags flags )
{
if ( !layer )
return false;
Expand Down Expand Up @@ -1015,9 +1016,12 @@ bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, c

if ( layer->joinBuffer()->containsJoins() )
{
const auto constVectorJoins = layer->joinBuffer()->vectorJoins();
for ( const QgsVectorLayerJoinInfo &info : constVectorJoins )
const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
for ( const QgsVectorLayerJoinInfo &info : joins )
{
if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
continue;

if ( info.isEditable() && info.hasCascadedDelete() )
{
QgsFeatureIds joinFeatureIds;
Expand Down
13 changes: 12 additions & 1 deletion src/core/qgsvectorlayerutils.h
Expand Up @@ -322,13 +322,24 @@ class CORE_EXPORT QgsVectorLayerUtils
*/
static QString getFeatureDisplayString( const QgsVectorLayer *layer, const QgsFeature &feature );

/**
* Flags that can be used when determining cascaded features.
*
* \since QGIS 3.4
*/
enum CascadedFeatureFlag
{
IgnoreAuxiliaryLayers = 1 << 1, //!< Ignore auxiliary layers
};
Q_DECLARE_FLAGS( CascadedFeatureFlags, CascadedFeatureFlag )

/**
* \returns TRUE if at least one feature of the \a fids on \a layer is connected as parent in at
* least one composition relation of the \a project or contains joins, where cascade delete is set.
* Details about cascading effects will be written to \a context.
* \since QGIS 3.14
*/
static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context SIP_OUT );
static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context SIP_OUT, CascadedFeatureFlags flags = CascadedFeatureFlags() );

};

Expand Down

0 comments on commit 8c79b94

Please sign in to comment.