Skip to content

Commit 348b0cf

Browse files
authoredFeb 20, 2018
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.
1 parent 1582073 commit 348b0cf

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed
 

‎src/app/qgisapp.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,7 +1902,7 @@ void QgisApp::createActions()
19021902
connect( mActionReshapeFeatures, &QAction::triggered, this, &QgisApp::reshapeFeatures );
19031903
connect( mActionSplitFeatures, &QAction::triggered, this, &QgisApp::splitFeatures );
19041904
connect( mActionSplitParts, &QAction::triggered, this, &QgisApp::splitParts );
1905-
connect( mActionDeleteSelected, &QAction::triggered, this, [ = ] { deleteSelected(); } );
1905+
connect( mActionDeleteSelected, &QAction::triggered, this, [ = ] { deleteSelected( nullptr, nullptr, true ); } );
19061906
connect( mActionAddRing, &QAction::triggered, this, &QgisApp::addRing );
19071907
connect( mActionFillRing, &QAction::triggered, this, &QgisApp::fillRing );
19081908
connect( mActionAddPart, &QAction::triggered, this, &QgisApp::addPart );
@@ -7090,7 +7090,7 @@ void QgisApp::layerProperties()
70907090
showLayerProperties( activeLayer() );
70917091
}
70927092

7093-
void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool promptConfirmation )
7093+
void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool checkFeaturesVisible )
70947094
{
70957095
if ( !layer )
70967096
{
@@ -7145,9 +7145,31 @@ void QgisApp::deleteSelected( QgsMapLayer *layer, QWidget *parent, bool promptCo
71457145
return;
71467146
}
71477147
//display a warning
7148-
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 )
7148+
if ( checkFeaturesVisible )
71497149
{
7150-
return;
7150+
QgsFeature feat;
7151+
QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
7152+
bool allFeaturesInView = true;
7153+
QgsRectangle viewRect = mMapCanvas->mapSettings().mapToLayerCoordinates( vlayer, mMapCanvas->extent() );
7154+
7155+
while ( it.nextFeature( feat ) )
7156+
{
7157+
if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) )
7158+
{
7159+
allFeaturesInView = false;
7160+
break;
7161+
}
7162+
}
7163+
7164+
if ( !allFeaturesInView )
7165+
{
7166+
// for extra safety to make sure we are not removing geometries by accident
7167+
int res = QMessageBox::warning( mMapCanvas, tr( "Delete features" ),
7168+
tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ),
7169+
QMessageBox::Yes | QMessageBox::No );
7170+
if ( res != QMessageBox::Yes )
7171+
return;
7172+
}
71517173
}
71527174

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

‎src/app/qgisapp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
821821
void loadGDALSublayers( const QString &uri, const QStringList &list );
822822

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

826826
//! project was written
827827
void writeProject( QDomDocument & );

‎src/app/qgsmaptoolmovefeature.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "qgsvectorlayertools.h"
2727

2828

29+
#include <QMessageBox>
2930
#include <QMouseEvent>
3031
#include <QSettings>
3132
#include <limits>
@@ -128,9 +129,31 @@ void QgsMapToolMoveFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
128129
QgsFeature feat;
129130
QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
130131

132+
bool allFeaturesInView = true;
133+
QgsRectangle viewRect = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, mCanvas->extent() );
134+
131135
while ( it.nextFeature( feat ) )
132136
{
133137
mRubberBand->addGeometry( feat.geometry(), vlayer );
138+
139+
if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) )
140+
allFeaturesInView = false;
141+
}
142+
143+
if ( !allFeaturesInView )
144+
{
145+
// for extra safety to make sure we are not modifying geometries by accident
146+
147+
int res = QMessageBox::warning( mCanvas, tr( "Move features" ),
148+
tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ),
149+
QMessageBox::Yes | QMessageBox::No );
150+
if ( res != QMessageBox::Yes )
151+
{
152+
mMovedFeatures.clear();
153+
delete mRubberBand;
154+
mRubberBand = nullptr;
155+
return;
156+
}
134157
}
135158
}
136159

0 commit comments

Comments
 (0)
Please sign in to comment.