Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Warn user when trying to move or delete selected features outside of …
…map view (#6092)

Sometimes users may inadvertently move/delete features they are not aware
of being selected. If that is the case, extra warning message box will be shown
for confirmation.

Does not apply for deletion from attribute table - it is assumed that features
do not need to be visible when deleting from attribute table.

In QgisApp::deleteSelected() method the last argument was not used anymore,
so I have replaced it by the "checkFeaturesVisible" argument.
  • Loading branch information
wonder-sk committed Feb 20, 2018
1 parent 1582073 commit 348b0cf
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
32 changes: 27 additions & 5 deletions src/app/qgisapp.cpp
Expand Up @@ -1902,7 +1902,7 @@ void QgisApp::createActions()
connect( mActionReshapeFeatures, &QAction::triggered, this, &QgisApp::reshapeFeatures );
connect( mActionSplitFeatures, &QAction::triggered, this, &QgisApp::splitFeatures );
connect( mActionSplitParts, &QAction::triggered, this, &QgisApp::splitParts );
connect( mActionDeleteSelected, &QAction::triggered, this, [ = ] { deleteSelected(); } );
connect( mActionDeleteSelected, &QAction::triggered, this, [ = ] { deleteSelected( nullptr, nullptr, true ); } );
connect( mActionAddRing, &QAction::triggered, this, &QgisApp::addRing );
connect( mActionFillRing, &QAction::triggered, this, &QgisApp::fillRing );
connect( mActionAddPart, &QAction::triggered, this, &QgisApp::addPart );
Expand Down Expand Up @@ -7090,7 +7090,7 @@ void QgisApp::layerProperties()
showLayerProperties( activeLayer() );
}

void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool promptConfirmation )
void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFeaturesVisible )
{
if ( !layer )
{
Expand Down Expand Up @@ -7145,9 +7145,31 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool promptCo
return;
}
//display a warning
if ( promptConfirmation && QMessageBox::warning( parent, tr( "Delete Features" ), tr( "Delete %n feature(s)?", "number of features to delete", numberOfSelectedFeatures ), QMessageBox::Ok | QMessageBox::Cancel ) == QMessageBox::Cancel )
if ( checkFeaturesVisible )
{
return;
QgsFeature feat;
QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
bool allFeaturesInView = true;
QgsRectangle viewRect = mMapCanvas->mapSettings().mapToLayerCoordinates( vlayer, mMapCanvas->extent() );

while ( it.nextFeature( feat ) )
{
if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) )
{
allFeaturesInView = false;
break;
}
}

if ( !allFeaturesInView )
{
// for extra safety to make sure we are not removing geometries by accident
int res = QMessageBox::warning( mMapCanvas, tr( "Delete features" ),
tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
return;
}
}

vlayer->beginEditCommand( tr( "Features deleted" ) );
Expand Down Expand Up @@ -12272,7 +12294,7 @@ void QgisApp::mapCanvas_keyPressed( QKeyEvent *e )
// Delete selected features when it is possible and KeyEvent was not managed by current MapTool
if ( ( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) && e->isAccepted() )
{
deleteSelected();
deleteSelected( nullptr, nullptr, true );
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/qgisapp.h
Expand Up @@ -821,7 +821,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void loadGDALSublayers( const QString &uri, const QStringList &list );

//! Deletes the selected attributes for the currently selected vector layer
void deleteSelected( QgsMapLayer *layer = nullptr, QWidget *parent = nullptr, bool promptConfirmation = false );
void deleteSelected( QgsMapLayer *layer = nullptr, QWidget *parent = nullptr, bool checkFeaturesVisible = false );

//! project was written
void writeProject( QDomDocument & );
Expand Down
23 changes: 23 additions & 0 deletions src/app/qgsmaptoolmovefeature.cpp
Expand Up @@ -26,6 +26,7 @@
#include "qgsvectorlayertools.h"


#include <QMessageBox>
#include <QMouseEvent>
#include <QSettings>
#include <limits>
Expand Down Expand Up @@ -128,9 +129,31 @@ void QgsMapToolMoveFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
QgsFeature feat;
QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );

bool allFeaturesInView = true;
QgsRectangle viewRect = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, mCanvas->extent() );

while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );

if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) )
allFeaturesInView = false;
}

if ( !allFeaturesInView )
{
// for extra safety to make sure we are not modifying geometries by accident

int res = QMessageBox::warning( mCanvas, tr( "Move features" ),
tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ),
QMessageBox::Yes | QMessageBox::No );
if ( res != QMessageBox::Yes )
{
mMovedFeatures.clear();
delete mRubberBand;
mRubberBand = nullptr;
return;
}
}
}

Expand Down

0 comments on commit 348b0cf

Please sign in to comment.