Skip to content
Permalink
Browse files

Don't show cascaded feature deletion warnings and feedback if

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 8c79b94fcc14e41d4442a018554e889f81b8e080
@@ -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;
@@ -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
@@ -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;
@@ -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;
@@ -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;
@@ -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 )
{
@@ -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;
}

@@ -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;
@@ -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 )
{
@@ -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;
@@ -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;
@@ -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() );

};

0 comments on commit 8c79b94

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